Chapter 3 Abstract: Ecological niche can drive the genomic diversification of closely related bacterial species. Here, I apply genomic analyses to the genus Psychrobacter, known for its particularly wide ecological distribution. I performed a pan-genome analysis, microbial pan-genome wide association, ancestral character estimations, and analysis of selection on protein sequences of 85 strains of Psychrobacter to clarify the interactions between isolation source and Psychrobacter genome evolution. There is some evidence that Psychrobacter isolation source correlates with available gene pool; each isolation source - from warm-bodied hosts such as mammals or birds, other hosts like fish or invertebrates, to food processing, marine, or terrestrial environments - is correlated with unique genes from different COG categories. Strains isolated from invertebrate and fish hosts, as well as food processing environments, have higher numbers of total genes, though fewer unique genes than strains from mammals, birds, or marine environments. After accounting for population structure, however, very few genes correlate with isolation source; there is some evidence for increased horizontal gene transfer in strains isolated from fish and invertebrates, and evidence for increased biofilm formation in strains isolated from food-processing environments. Ancestral character estimation supports that Psychrobacter are descended from a warm host-associated bacterium. Finally, there is no correlation between isolation source and cold-adaptation of proteins. Overall, my results show that isolation source has some impact on Psychrobacter genome evolution, though the population structure of the genus makes it difficult to disentangle its effects.

The working directory was changed to /Users/dwelter/ownCloud/Psychrobacter/Data_Analysis/PANX/thesis inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the the working directory for notebook chunks.
Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union


Attaching package: ‘seqinr’

The following object is masked from ‘package:dplyr’:

    count


Attaching package: ‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths

Loading required package: ape

Attaching package: ‘ape’

The following objects are masked from ‘package:seqinr’:

    as.alignment, consensus

The following object is masked from ‘package:ggpubr’:

    rotate

Loading required package: maps
Loading required package: microseq
Loading required package: tibble
Loading required package: data.table
data.table 1.13.0 using 1 threads (see ?getDTthreads).  Latest news: r-datatable.com
**********
This installation of data.table has not detected OpenMP support. It should still work but in single-threaded mode.
This is a Mac. Please read https://mac.r-project.org/openmp/. Please engage with Apple and ask them for support. Check r-datatable.com for updates, and our Mac instructions here: https://github.com/Rdatatable/data.table/wiki/Installation. After several years of many reports of installation problems on Mac, it's time to gingerly point out that there have been no similar problems on Windows or Linux.
**********

Attaching package: ‘data.table’

The following objects are masked from ‘package:reshape2’:

    dcast, melt

The following objects are masked from ‘package:dplyr’:

    between, first, last

Loading required package: rlang

Attaching package: ‘rlang’

The following object is masked from ‘package:data.table’:

    :=


Attaching package: ‘microseq’

The following object is masked from ‘package:ape’:

    muscle

The following object is masked from ‘package:seqinr’:

    translate

The following object is masked from ‘package:base’:

    gregexpr

Loading required package: igraph

Attaching package: ‘igraph’

The following object is masked from ‘package:rlang’:

    is_named

The following object is masked from ‘package:tibble’:

    as_data_frame

The following objects are masked from ‘package:ape’:

    edges, mst, ring

The following object is masked from ‘package:tidyr’:

    crossing

The following objects are masked from ‘package:dplyr’:

    as_data_frame, groups, union

The following objects are masked from ‘package:stats’:

    decompose, spectrum

The following object is masked from ‘package:base’:

    union

corrplot 0.84 loaded
Loading required package: adegenet
Loading required package: ade4
Registered S3 method overwritten by 'spdep':
  method   from
  plot.mst ape 

   /// adegenet 2.1.3 is loaded ////////////

   > overview: '?adegenet'
   > tutorials/doc/questions: 'adegenetWeb()' 
   > bug reports/feature requests: adegenetIssues()



Attaching package: ‘adegenet’

The following object is masked from ‘package:rlang’:

    chr

Registered S3 method overwritten by 'pryr':
  method      from
  print.bytes Rcpp
R version 3.6.3 (2020-02-29)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: OS X El Capitan 10.11.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] treeWAS_1.0       adegenet_2.1.3    ade4_1.7-15       corrplot_0.84    
 [5] micropan_2.1      igraph_1.2.5      microseq_2.1.2    rlang_0.4.7      
 [9] data.table_1.13.0 tibble_3.0.3      phytools_0.7-47   maps_3.3.0       
[13] ape_5.4-1         reshape2_1.4.4    seqinr_3.6-1      ggsignif_0.6.0   
[17] ggpubr_0.4.0      tidyr_1.1.2       dplyr_1.0.2       ggplot2_3.3.2    
[21] stringr_1.4.0    

loaded via a namespace (and not attached):
  [1] colorspace_1.4-1        pryr_0.1.4              deldir_0.1-28          
  [4] ellipsis_0.3.1          class_7.3-17            rio_0.5.16             
  [7] htmlTable_2.0.1         base64enc_0.1-3         rstudioapi_0.11        
 [10] codetools_0.2-16        splines_3.6.3           mnormt_2.0.2           
 [13] knitr_1.29              Formula_1.2-3           broom_0.7.0            
 [16] cluster_2.1.0           png_0.1-7               shiny_1.5.0            
 [19] compiler_3.6.3          backports_1.1.9         Matrix_1.2-18          
 [22] fastmap_1.0.1           later_1.1.0.1           htmltools_0.5.0        
 [25] tools_3.6.3             coda_0.19-3             gtable_0.3.0           
 [28] glue_1.4.2              clusterGeneration_1.3.4 gmodels_2.18.1         
 [31] fastmatch_1.1-0         Rcpp_1.0.5              carData_3.0-4          
 [34] cellranger_1.1.0        raster_3.3-13           vctrs_0.3.4            
 [37] spdep_1.1-5             gdata_2.18.0            nlme_3.1-149           
 [40] xfun_0.16               openxlsx_4.1.5          mime_0.9               
 [43] lifecycle_0.2.0         phangorn_2.5.5          gtools_3.8.2           
 [46] rstatix_0.6.0           LearnBayes_2.15.1       MASS_7.3-52            
 [49] scales_1.1.1            hms_0.5.3               promises_1.1.1         
 [52] parallel_3.6.3          expm_0.999-5            RColorBrewer_1.1-2     
 [55] animation_2.6           curl_4.3                gridExtra_2.3          
 [58] rpart_4.1-15            latticeExtra_0.6-29     stringi_1.4.6          
 [61] plotrix_3.7-8           checkmate_2.0.0         e1071_1.7-3            
 [64] permute_0.9-5           boot_1.3-25             zip_2.1.1              
 [67] spData_0.3.8            pkgconfig_2.0.3         lattice_0.20-41        
 [70] purrr_0.3.4             sf_0.9-5                htmlwidgets_1.5.1      
 [73] tidyselect_1.1.0        plyr_1.8.6              magrittr_1.5           
 [76] R6_2.4.1                generics_0.0.2          Hmisc_4.4-1            
 [79] combinat_0.0-8          DBI_1.1.0               pillar_1.4.6           
 [82] haven_2.3.1             foreign_0.8-75          withr_2.2.0            
 [85] mgcv_1.8-33             units_0.6-7             nnet_7.3-14            
 [88] survival_3.2-3          scatterplot3d_0.3-41    abind_1.4-5            
 [91] sp_1.4-2                crayon_1.3.4            car_3.0-9              
 [94] KernSmooth_2.23-17      tmvnsim_1.0-2           jpeg_0.1-8.1           
 [97] grid_3.6.3              readxl_1.3.1            vegan_2.5-6            
[100] forcats_0.5.0           digest_0.6.25           classInt_0.4-3         
[103] xtable_1.8-4            httpuv_1.5.4            numDeriv_2016.8-1.1    
[106] munsell_0.5.0           beeswarm_0.2.3          quadprog_1.5-8         
sessionInfo()

Pan-genome summary

genematrix = psych_gpa[,10:ncol(psych_gpa)] #or whichever column your isolate data starts at
rownames(genematrix) = psych_gpa$geneCluster
genematrix = apply(genematrix,  2,  function(x) gsub("^$|^ $",  NA,  x)) #replace empty cells with NA
transform_func = function(x) { if (is.na(x) > 0) { r = 0 } else { r = 1 } } #creates a function to recognize when a cell has information in it (in this case,  when an isolate HAS a gene) and replace that cell's contents with "1". otherwise,  replace that cell's contents with "0"
genematrix_binary <- apply(genematrix, 2, function(x){sapply(x,  transform_func)}) #loop the function created in the step above through our transposed gene matrix
genematrix_binary_t = t(genematrix_binary) #transpose the matrix; need strains to be on the rows and genes to be on the columns
genematrix_binary_t = as.data.frame(genematrix_binary_t)
genematrix_binary_t = genematrix_binary_t %>%
  mutate_if(is.factor, as.numeric) #t() will transform your data into the "matrix" format, and treewas wants it in a dataframe format, so this transforms it back
rownames(genematrix_binary_t) = colnames(genematrix_binary)
#to produce output file "genematrix_for_treewas_fixeddashes.txt"
genes_mat = genematrix 
genes_mat_numbered = genes_mat
for(i in 1:nrow(genes_mat)) {
  for (j in 1:ncol(genes_mat)) {
    cell = genes_mat[i,j]
    num = str_count(cell, ",") + 1
    if (is.na(cell) == TRUE) {num = 0}
    genes_mat_numbered[i,j] = num
  }
}
rownames(genes_mat_numbered) = psych_gpa$geneCluster
genes_mat_numbered = as.data.frame(genes_mat_numbered)
genes_mat_numbered = genes_mat_numbered %>%
  mutate_all(as.character) %>%
  mutate_all(as.numeric)
library(micropan)
genes_mat_forpan = t(genes_mat_numbered)
colnames(genes_mat_forpan) = rownames(genes_mat)
rare = rarefaction(pan.matrix = genes_mat_forpan, n.perm = 999)
2 / 999 
3 / 999 
4 / 999 
5 / 999 
6 / 999 
7 / 999 
8 / 999 
9 / 999 
10 / 999 
11 / 999 
12 / 999 
13 / 999 
14 / 999 
15 / 999 
16 / 999 
17 / 999 
18 / 999 
19 / 999 
20 / 999 
21 / 999 
22 / 999 
23 / 999 
24 / 999 
25 / 999 
26 / 999 
27 / 999 
28 / 999 
29 / 999 
30 / 999 
31 / 999 
32 / 999 
33 / 999 
34 / 999 
35 / 999 
36 / 999 
37 / 999 
38 / 999 
39 / 999 
40 / 999 
41 / 999 
42 / 999 
43 / 999 
44 / 999 
45 / 999 
46 / 999 
47 / 999 
48 / 999 
49 / 999 
50 / 999 
51 / 999 
52 / 999 
53 / 999 
54 / 999 
55 / 999 
56 / 999 
57 / 999 
58 / 999 
59 / 999 
60 / 999 
61 / 999 
62 / 999 
63 / 999 
64 / 999 
65 / 999 
66 / 999 
67 / 999 
68 / 999 
69 / 999 
70 / 999 
71 / 999 
72 / 999 
73 / 999 
74 / 999 
75 / 999 
76 / 999 
77 / 999 
78 / 999 
79 / 999 
80 / 999 
81 / 999 
82 / 999 
83 / 999 
84 / 999 
85 / 999 
86 / 999 
87 / 999 
88 / 999 
89 / 999 
90 / 999 
91 / 999 
92 / 999 
93 / 999 
94 / 999 
95 / 999 
96 / 999 
97 / 999 
98 / 999 
99 / 999 
100 / 999 
101 / 999 
102 / 999 
103 / 999 
104 / 999 
105 / 999 
106 / 999 
107 / 999 
108 / 999 
109 / 999 
110 / 999 
111 / 999 
112 / 999 
113 / 999 
114 / 999 
115 / 999 
116 / 999 
117 / 999 
118 / 999 
119 / 999 
120 / 999 
121 / 999 
122 / 999 
123 / 999 
124 / 999 
125 / 999 
126 / 999 
127 / 999 
128 / 999 
129 / 999 
130 / 999 
131 / 999 
132 / 999 
133 / 999 
134 / 999 
135 / 999 
136 / 999 
137 / 999 
138 / 999 
139 / 999 
140 / 999 
141 / 999 
142 / 999 
143 / 999 
144 / 999 
145 / 999 
146 / 999 
147 / 999 
148 / 999 
149 / 999 
150 / 999 
151 / 999 
152 / 999 
153 / 999 
154 / 999 
155 / 999 
156 / 999 
157 / 999 
158 / 999 
159 / 999 
160 / 999 
161 / 999 
162 / 999 
163 / 999 
164 / 999 
165 / 999 
166 / 999 
167 / 999 
168 / 999 
169 / 999 
170 / 999 
171 / 999 
172 / 999 
173 / 999 
174 / 999 
175 / 999 
176 / 999 
177 / 999 
178 / 999 
179 / 999 
180 / 999 
181 / 999 
182 / 999 
183 / 999 
184 / 999 
185 / 999 
186 / 999 
187 / 999 
188 / 999 
189 / 999 
190 / 999 
191 / 999 
192 / 999 
193 / 999 
194 / 999 
195 / 999 
196 / 999 
197 / 999 
198 / 999 
199 / 999 
200 / 999 
201 / 999 
202 / 999 
203 / 999 
204 / 999 
205 / 999 
206 / 999 
207 / 999 
208 / 999 
209 / 999 
210 / 999 
211 / 999 
212 / 999 
213 / 999 
214 / 999 
215 / 999 
216 / 999 
217 / 999 
218 / 999 
219 / 999 
220 / 999 
221 / 999 
222 / 999 
223 / 999 
224 / 999 
225 / 999 
226 / 999 
227 / 999 
228 / 999 
229 / 999 
230 / 999 
231 / 999 
232 / 999 
233 / 999 
234 / 999 
235 / 999 
236 / 999 
237 / 999 
238 / 999 
239 / 999 
240 / 999 
241 / 999 
242 / 999 
243 / 999 
244 / 999 
245 / 999 
246 / 999 
247 / 999 
248 / 999 
249 / 999 
250 / 999 
251 / 999 
252 / 999 
253 / 999 
254 / 999 
255 / 999 
256 / 999 
257 / 999 
258 / 999 
259 / 999 
260 / 999 
261 / 999 
262 / 999 
263 / 999 
264 / 999 
265 / 999 
266 / 999 
267 / 999 
268 / 999 
269 / 999 
270 / 999 
271 / 999 
272 / 999 
273 / 999 
274 / 999 
275 / 999 
276 / 999 
277 / 999 
278 / 999 
279 / 999 
280 / 999 
281 / 999 
282 / 999 
283 / 999 
284 / 999 
285 / 999 
286 / 999 
287 / 999 
288 / 999 
289 / 999 
290 / 999 
291 / 999 
292 / 999 
293 / 999 
294 / 999 
295 / 999 
296 / 999 
297 / 999 
298 / 999 
299 / 999 
300 / 999 
301 / 999 
302 / 999 
303 / 999 
304 / 999 
305 / 999 
306 / 999 
307 / 999 
308 / 999 
309 / 999 
310 / 999 
311 / 999 
312 / 999 
313 / 999 
314 / 999 
315 / 999 
316 / 999 
317 / 999 
318 / 999 
319 / 999 
320 / 999 
321 / 999 
322 / 999 
323 / 999 
324 / 999 
325 / 999 
326 / 999 
327 / 999 
328 / 999 
329 / 999 
330 / 999 
331 / 999 
332 / 999 
333 / 999 
334 / 999 
335 / 999 
336 / 999 
337 / 999 
338 / 999 
339 / 999 
340 / 999 
341 / 999 
342 / 999 
343 / 999 
344 / 999 
345 / 999 
346 / 999 
347 / 999 
348 / 999 
349 / 999 
350 / 999 
351 / 999 
352 / 999 
353 / 999 
354 / 999 
355 / 999 
356 / 999 
357 / 999 
358 / 999 
359 / 999 
360 / 999 
361 / 999 
362 / 999 
363 / 999 
364 / 999 
365 / 999 
366 / 999 
367 / 999 
368 / 999 
369 / 999 
370 / 999 
371 / 999 
372 / 999 
373 / 999 
374 / 999 
375 / 999 
376 / 999 
377 / 999 
378 / 999 
379 / 999 
380 / 999 
381 / 999 
382 / 999 
383 / 999 
384 / 999 
385 / 999 
386 / 999 
387 / 999 
388 / 999 
389 / 999 
390 / 999 
391 / 999 
392 / 999 
393 / 999 
394 / 999 
395 / 999 
396 / 999 
397 / 999 
398 / 999 
399 / 999 
400 / 999 
401 / 999 
402 / 999 
403 / 999 
404 / 999 
405 / 999 
406 / 999 
407 / 999 
408 / 999 
409 / 999 
410 / 999 
411 / 999 
412 / 999 
413 / 999 
414 / 999 
415 / 999 
416 / 999 
417 / 999 
418 / 999 
419 / 999 
420 / 999 
421 / 999 
422 / 999 
423 / 999 
424 / 999 
425 / 999 
426 / 999 
427 / 999 
428 / 999 
429 / 999 
430 / 999 
431 / 999 
432 / 999 
433 / 999 
434 / 999 
435 / 999 
436 / 999 
437 / 999 
438 / 999 
439 / 999 
440 / 999 
441 / 999 
442 / 999 
443 / 999 
444 / 999 
445 / 999 
446 / 999 
447 / 999 
448 / 999 
449 / 999 
450 / 999 
451 / 999 
452 / 999 
453 / 999 
454 / 999 
455 / 999 
456 / 999 
457 / 999 
458 / 999 
459 / 999 
460 / 999 
461 / 999 
462 / 999 
463 / 999 
464 / 999 
465 / 999 
466 / 999 
467 / 999 
468 / 999 
469 / 999 
470 / 999 
471 / 999 
472 / 999 
473 / 999 
474 / 999 
475 / 999 
476 / 999 
477 / 999 
478 / 999 
479 / 999 
480 / 999 
481 / 999 
482 / 999 
483 / 999 
484 / 999 
485 / 999 
486 / 999 
487 / 999 
488 / 999 
489 / 999 
490 / 999 
491 / 999 
492 / 999 
493 / 999 
494 / 999 
495 / 999 
496 / 999 
497 / 999 
498 / 999 
499 / 999 
500 / 999 
501 / 999 
502 / 999 
503 / 999 
504 / 999 
505 / 999 
506 / 999 
507 / 999 
508 / 999 
509 / 999 
510 / 999 
511 / 999 
512 / 999 
513 / 999 
514 / 999 
515 / 999 
516 / 999 
517 / 999 
518 / 999 
519 / 999 
520 / 999 
521 / 999 
522 / 999 
523 / 999 
524 / 999 
525 / 999 
526 / 999 
527 / 999 
528 / 999 
529 / 999 
530 / 999 
531 / 999 
532 / 999 
533 / 999 
534 / 999 
535 / 999 
536 / 999 
537 / 999 
538 / 999 
539 / 999 
540 / 999 
541 / 999 
542 / 999 
543 / 999 
544 / 999 
545 / 999 
546 / 999 
547 / 999 
548 / 999 
549 / 999 
550 / 999 
551 / 999 
552 / 999 
553 / 999 
554 / 999 
555 / 999 
556 / 999 
557 / 999 
558 / 999 
559 / 999 
560 / 999 
561 / 999 
562 / 999 
563 / 999 
564 / 999 
565 / 999 
566 / 999 
567 / 999 
568 / 999 
569 / 999 
570 / 999 
571 / 999 
572 / 999 
573 / 999 
574 / 999 
575 / 999 
576 / 999 
577 / 999 
578 / 999 
579 / 999 
580 / 999 
581 / 999 
582 / 999 
583 / 999 
584 / 999 
585 / 999 
586 / 999 
587 / 999 
588 / 999 
589 / 999 
590 / 999 
591 / 999 
592 / 999 
593 / 999 
594 / 999 
595 / 999 
596 / 999 
597 / 999 
598 / 999 
599 / 999 
600 / 999 
601 / 999 
602 / 999 
603 / 999 
604 / 999 
605 / 999 
606 / 999 
607 / 999 
608 / 999 
609 / 999 
610 / 999 
611 / 999 
612 / 999 
613 / 999 
614 / 999 
615 / 999 
616 / 999 
617 / 999 
618 / 999 
619 / 999 
620 / 999 
621 / 999 
622 / 999 
623 / 999 
624 / 999 
625 / 999 
626 / 999 
627 / 999 
628 / 999 
629 / 999 
630 / 999 
631 / 999 
632 / 999 
633 / 999 
634 / 999 
635 / 999 
636 / 999 
637 / 999 
638 / 999 
639 / 999 
640 / 999 
641 / 999 
642 / 999 
643 / 999 
644 / 999 
645 / 999 
646 / 999 
647 / 999 
648 / 999 
649 / 999 
650 / 999 
651 / 999 
652 / 999 
653 / 999 
654 / 999 
655 / 999 
656 / 999 
657 / 999 
658 / 999 
659 / 999 
660 / 999 
661 / 999 
662 / 999 
663 / 999 
664 / 999 
665 / 999 
666 / 999 
667 / 999 
668 / 999 
669 / 999 
670 / 999 
671 / 999 
672 / 999 
673 / 999 
674 / 999 
675 / 999 
676 / 999 
677 / 999 
678 / 999 
679 / 999 
680 / 999 
681 / 999 
682 / 999 
683 / 999 
684 / 999 
685 / 999 
686 / 999 
687 / 999 
688 / 999 
689 / 999 
690 / 999 
691 / 999 
692 / 999 
693 / 999 
694 / 999 
695 / 999 
696 / 999 
697 / 999 
698 / 999 
699 / 999 
700 / 999 
701 / 999 
702 / 999 
703 / 999 
704 / 999 
705 / 999 
706 / 999 
707 / 999 
708 / 999 
709 / 999 
710 / 999 
711 / 999 
712 / 999 
713 / 999 
714 / 999 
715 / 999 
716 / 999 
717 / 999 
718 / 999 
719 / 999 
720 / 999 
721 / 999 
722 / 999 
723 / 999 
724 / 999 
725 / 999 
726 / 999 
727 / 999 
728 / 999 
729 / 999 
730 / 999 
731 / 999 
732 / 999 
733 / 999 
734 / 999 
735 / 999 
736 / 999 
737 / 999 
738 / 999 
739 / 999 
740 / 999 
741 / 999 
742 / 999 
743 / 999 
744 / 999 
745 / 999 
746 / 999 
747 / 999 
748 / 999 
749 / 999 
750 / 999 
751 / 999 
752 / 999 
753 / 999 
754 / 999 
755 / 999 
756 / 999 
757 / 999 
758 / 999 
759 / 999 
760 / 999 
761 / 999 
762 / 999 
763 / 999 
764 / 999 
765 / 999 
766 / 999 
767 / 999 
768 / 999 
769 / 999 
770 / 999 
771 / 999 
772 / 999 
773 / 999 
774 / 999 
775 / 999 
776 / 999 
777 / 999 
778 / 999 
779 / 999 
780 / 999 
781 / 999 
782 / 999 
783 / 999 
784 / 999 
785 / 999 
786 / 999 
787 / 999 
788 / 999 
789 / 999 
790 / 999 
791 / 999 
792 / 999 
793 / 999 
794 / 999 
795 / 999 
796 / 999 
797 / 999 
798 / 999 
799 / 999 
800 / 999 
801 / 999 
802 / 999 
803 / 999 
804 / 999 
805 / 999 
806 / 999 
807 / 999 
808 / 999 
809 / 999 
810 / 999 
811 / 999 
812 / 999 
813 / 999 
814 / 999 
815 / 999 
816 / 999 
817 / 999 
818 / 999 
819 / 999 
820 / 999 
821 / 999 
822 / 999 
823 / 999 
824 / 999 
825 / 999 
826 / 999 
827 / 999 
828 / 999 
829 / 999 
830 / 999 
831 / 999 
832 / 999 
833 / 999 
834 / 999 
835 / 999 
836 / 999 
837 / 999 
838 / 999 
839 / 999 
840 / 999 
841 / 999 
842 / 999 
843 / 999 
844 / 999 
845 / 999 
846 / 999 
847 / 999 
848 / 999 
849 / 999 
850 / 999 
851 / 999 
852 / 999 
853 / 999 
854 / 999 
855 / 999 
856 / 999 
857 / 999 
858 / 999 
859 / 999 
860 / 999 
861 / 999 
862 / 999 
863 / 999 
864 / 999 
865 / 999 
866 / 999 
867 / 999 
868 / 999 
869 / 999 
870 / 999 
871 / 999 
872 / 999 
873 / 999 
874 / 999 
875 / 999 
876 / 999 
877 / 999 
878 / 999 
879 / 999 
880 / 999 
881 / 999 
882 / 999 
883 / 999 
884 / 999 
885 / 999 
886 / 999 
887 / 999 
888 / 999 
889 / 999 
890 / 999 
891 / 999 
892 / 999 
893 / 999 
894 / 999 
895 / 999 
896 / 999 
897 / 999 
898 / 999 
899 / 999 
900 / 999 
901 / 999 
902 / 999 
903 / 999 
904 / 999 
905 / 999 
906 / 999 
907 / 999 
908 / 999 
909 / 999 
910 / 999 
911 / 999 
912 / 999 
913 / 999 
914 / 999 
915 / 999 
916 / 999 
917 / 999 
918 / 999 
919 / 999 
920 / 999 
921 / 999 
922 / 999 
923 / 999 
924 / 999 
925 / 999 
926 / 999 
927 / 999 
928 / 999 
929 / 999 
930 / 999 
931 / 999 
932 / 999 
933 / 999 
934 / 999 
935 / 999 
936 / 999 
937 / 999 
938 / 999 
939 / 999 
940 / 999 
941 / 999 
942 / 999 
943 / 999 
944 / 999 
945 / 999 
946 / 999 
947 / 999 
948 / 999 
949 / 999 
950 / 999 
951 / 999 
952 / 999 
953 / 999 
954 / 999 
955 / 999 
956 / 999 
957 / 999 
958 / 999 
959 / 999 
960 / 999 
961 / 999 
962 / 999 
963 / 999 
964 / 999 
965 / 999 
966 / 999 
967 / 999 
968 / 999 
969 / 999 
970 / 999 
971 / 999 
972 / 999 
973 / 999 
974 / 999 
975 / 999 
976 / 999 
977 / 999 
978 / 999 
979 / 999 
980 / 999 
981 / 999 
982 / 999 
983 / 999 
984 / 999 
985 / 999 
986 / 999 
987 / 999 
988 / 999 
989 / 999 
990 / 999 
991 / 999 
992 / 999 
993 / 999 
994 / 999 
995 / 999 
996 / 999 
997 / 999 
998 / 999 
999 / 999 
New names:
* `` -> ...2
* `` -> ...3
* `` -> ...4
* `` -> ...5
* `` -> ...6
* ...
rare.melt = reshape2::melt(rare, id = c("Genome"))
(panrarefaction = ggplot(data = rare.melt, aes(x = Genome, y = value)) + 
    geom_boxplot(aes(x = Genome, group = Genome), outlier.shape = NA) + 
    theme_classic() + 
    xlab("Number of Genomes") + ylab("Number of Novel Orthologs"))

heaps(pan.matrix = genes_mat_forpan, n.perm = 999)
1 / 999 
2 / 999 
3 / 999 
4 / 999 
5 / 999 
6 / 999 
7 / 999 
8 / 999 
9 / 999 
10 / 999 
11 / 999 
12 / 999 
13 / 999 
14 / 999 
15 / 999 
16 / 999 
17 / 999 
18 / 999 
19 / 999 
20 / 999 
21 / 999 
22 / 999 
23 / 999 
24 / 999 
25 / 999 
26 / 999 
27 / 999 
28 / 999 
29 / 999 
30 / 999 
31 / 999 
32 / 999 
33 / 999 
34 / 999 
35 / 999 
36 / 999 
37 / 999 
38 / 999 
39 / 999 
40 / 999 
41 / 999 
42 / 999 
43 / 999 
44 / 999 
45 / 999 
46 / 999 
47 / 999 
48 / 999 
49 / 999 
50 / 999 
51 / 999 
52 / 999 
53 / 999 
54 / 999 
55 / 999 
56 / 999 
57 / 999 
58 / 999 
59 / 999 
60 / 999 
61 / 999 
62 / 999 
63 / 999 
64 / 999 
65 / 999 
66 / 999 
67 / 999 
68 / 999 
69 / 999 
70 / 999 
71 / 999 
72 / 999 
73 / 999 
74 / 999 
75 / 999 
76 / 999 
77 / 999 
78 / 999 
79 / 999 
80 / 999 
81 / 999 
82 / 999 
83 / 999 
84 / 999 
85 / 999 
86 / 999 
87 / 999 
88 / 999 
89 / 999 
90 / 999 
91 / 999 
92 / 999 
93 / 999 
94 / 999 
95 / 999 
96 / 999 
97 / 999 
98 / 999 
99 / 999 
100 / 999 
101 / 999 
102 / 999 
103 / 999 
104 / 999 
105 / 999 
106 / 999 
107 / 999 
108 / 999 
109 / 999 
110 / 999 
111 / 999 
112 / 999 
113 / 999 
114 / 999 
115 / 999 
116 / 999 
117 / 999 
118 / 999 
119 / 999 
120 / 999 
121 / 999 
122 / 999 
123 / 999 
124 / 999 
125 / 999 
126 / 999 
127 / 999 
128 / 999 
129 / 999 
130 / 999 
131 / 999 
132 / 999 
133 / 999 
134 / 999 
135 / 999 
136 / 999 
137 / 999 
138 / 999 
139 / 999 
140 / 999 
141 / 999 
142 / 999 
143 / 999 
144 / 999 
145 / 999 
146 / 999 
147 / 999 
148 / 999 
149 / 999 
150 / 999 
151 / 999 
152 / 999 
153 / 999 
154 / 999 
155 / 999 
156 / 999 
157 / 999 
158 / 999 
159 / 999 
160 / 999 
161 / 999 
162 / 999 
163 / 999 
164 / 999 
165 / 999 
166 / 999 
167 / 999 
168 / 999 
169 / 999 
170 / 999 
171 / 999 
172 / 999 
173 / 999 
174 / 999 
175 / 999 
176 / 999 
177 / 999 
178 / 999 
179 / 999 
180 / 999 
181 / 999 
182 / 999 
183 / 999 
184 / 999 
185 / 999 
186 / 999 
187 / 999 
188 / 999 
189 / 999 
190 / 999 
191 / 999 
192 / 999 
193 / 999 
194 / 999 
195 / 999 
196 / 999 
197 / 999 
198 / 999 
199 / 999 
200 / 999 
201 / 999 
202 / 999 
203 / 999 
204 / 999 
205 / 999 
206 / 999 
207 / 999 
208 / 999 
209 / 999 
210 / 999 
211 / 999 
212 / 999 
213 / 999 
214 / 999 
215 / 999 
216 / 999 
217 / 999 
218 / 999 
219 / 999 
220 / 999 
221 / 999 
222 / 999 
223 / 999 
224 / 999 
225 / 999 
226 / 999 
227 / 999 
228 / 999 
229 / 999 
230 / 999 
231 / 999 
232 / 999 
233 / 999 
234 / 999 
235 / 999 
236 / 999 
237 / 999 
238 / 999 
239 / 999 
240 / 999 
241 / 999 
242 / 999 
243 / 999 
244 / 999 
245 / 999 
246 / 999 
247 / 999 
248 / 999 
249 / 999 
250 / 999 
251 / 999 
252 / 999 
253 / 999 
254 / 999 
255 / 999 
256 / 999 
257 / 999 
258 / 999 
259 / 999 
260 / 999 
261 / 999 
262 / 999 
263 / 999 
264 / 999 
265 / 999 
266 / 999 
267 / 999 
268 / 999 
269 / 999 
270 / 999 
271 / 999 
272 / 999 
273 / 999 
274 / 999 
275 / 999 
276 / 999 
277 / 999 
278 / 999 
279 / 999 
280 / 999 
281 / 999 
282 / 999 
283 / 999 
284 / 999 
285 / 999 
286 / 999 
287 / 999 
288 / 999 
289 / 999 
290 / 999 
291 / 999 
292 / 999 
293 / 999 
294 / 999 
295 / 999 
296 / 999 
297 / 999 
298 / 999 
299 / 999 
300 / 999 
301 / 999 
302 / 999 
303 / 999 
304 / 999 
305 / 999 
306 / 999 
307 / 999 
308 / 999 
309 / 999 
310 / 999 
311 / 999 
312 / 999 
313 / 999 
314 / 999 
315 / 999 
316 / 999 
317 / 999 
318 / 999 
319 / 999 
320 / 999 
321 / 999 
322 / 999 
323 / 999 
324 / 999 
325 / 999 
326 / 999 
327 / 999 
328 / 999 
329 / 999 
330 / 999 
331 / 999 
332 / 999 
333 / 999 
334 / 999 
335 / 999 
336 / 999 
337 / 999 
338 / 999 
339 / 999 
340 / 999 
341 / 999 
342 / 999 
343 / 999 
344 / 999 
345 / 999 
346 / 999 
347 / 999 
348 / 999 
349 / 999 
350 / 999 
351 / 999 
352 / 999 
353 / 999 
354 / 999 
355 / 999 
356 / 999 
357 / 999 
358 / 999 
359 / 999 
360 / 999 
361 / 999 
362 / 999 
363 / 999 
364 / 999 
365 / 999 
366 / 999 
367 / 999 
368 / 999 
369 / 999 
370 / 999 
371 / 999 
372 / 999 
373 / 999 
374 / 999 
375 / 999 
376 / 999 
377 / 999 
378 / 999 
379 / 999 
380 / 999 
381 / 999 
382 / 999 
383 / 999 
384 / 999 
385 / 999 
386 / 999 
387 / 999 
388 / 999 
389 / 999 
390 / 999 
391 / 999 
392 / 999 
393 / 999 
394 / 999 
395 / 999 
396 / 999 
397 / 999 
398 / 999 
399 / 999 
400 / 999 
401 / 999 
402 / 999 
403 / 999 
404 / 999 
405 / 999 
406 / 999 
407 / 999 
408 / 999 
409 / 999 
410 / 999 
411 / 999 
412 / 999 
413 / 999 
414 / 999 
415 / 999 
416 / 999 
417 / 999 
418 / 999 
419 / 999 
420 / 999 
421 / 999 
422 / 999 
423 / 999 
424 / 999 
425 / 999 
426 / 999 
427 / 999 
428 / 999 
429 / 999 
430 / 999 
431 / 999 
432 / 999 
433 / 999 
434 / 999 
435 / 999 
436 / 999 
437 / 999 
438 / 999 
439 / 999 
440 / 999 
441 / 999 
442 / 999 
443 / 999 
444 / 999 
445 / 999 
446 / 999 
447 / 999 
448 / 999 
449 / 999 
450 / 999 
451 / 999 
452 / 999 
453 / 999 
454 / 999 
455 / 999 
456 / 999 
457 / 999 
458 / 999 
459 / 999 
460 / 999 
461 / 999 
462 / 999 
463 / 999 
464 / 999 
465 / 999 
466 / 999 
467 / 999 
468 / 999 
469 / 999 
470 / 999 
471 / 999 
472 / 999 
473 / 999 
474 / 999 
475 / 999 
476 / 999 
477 / 999 
478 / 999 
479 / 999 
480 / 999 
481 / 999 
482 / 999 
483 / 999 
484 / 999 
485 / 999 
486 / 999 
487 / 999 
488 / 999 
489 / 999 
490 / 999 
491 / 999 
492 / 999 
493 / 999 
494 / 999 
495 / 999 
496 / 999 
497 / 999 
498 / 999 
499 / 999 
500 / 999 
501 / 999 
502 / 999 
503 / 999 
504 / 999 
505 / 999 
506 / 999 
507 / 999 
508 / 999 
509 / 999 
510 / 999 
511 / 999 
512 / 999 
513 / 999 
514 / 999 
515 / 999 
516 / 999 
517 / 999 
518 / 999 
519 / 999 
520 / 999 
521 / 999 
522 / 999 
523 / 999 
524 / 999 
525 / 999 
526 / 999 
527 / 999 
528 / 999 
529 / 999 
530 / 999 
531 / 999 
532 / 999 
533 / 999 
534 / 999 
535 / 999 
536 / 999 
537 / 999 
538 / 999 
539 / 999 
540 / 999 
541 / 999 
542 / 999 
543 / 999 
544 / 999 
545 / 999 
546 / 999 
547 / 999 
548 / 999 
549 / 999 
550 / 999 
551 / 999 
552 / 999 
553 / 999 
554 / 999 
555 / 999 
556 / 999 
557 / 999 
558 / 999 
559 / 999 
560 / 999 
561 / 999 
562 / 999 
563 / 999 
564 / 999 
565 / 999 
566 / 999 
567 / 999 
568 / 999 
569 / 999 
570 / 999 
571 / 999 
572 / 999 
573 / 999 
574 / 999 
575 / 999 
576 / 999 
577 / 999 
578 / 999 
579 / 999 
580 / 999 
581 / 999 
582 / 999 
583 / 999 
584 / 999 
585 / 999 
586 / 999 
587 / 999 
588 / 999 
589 / 999 
590 / 999 
591 / 999 
592 / 999 
593 / 999 
594 / 999 
595 / 999 
596 / 999 
597 / 999 
598 / 999 
599 / 999 
600 / 999 
601 / 999 
602 / 999 
603 / 999 
604 / 999 
605 / 999 
606 / 999 
607 / 999 
608 / 999 
609 / 999 
610 / 999 
611 / 999 
612 / 999 
613 / 999 
614 / 999 
615 / 999 
616 / 999 
617 / 999 
618 / 999 
619 / 999 
620 / 999 
621 / 999 
622 / 999 
623 / 999 
624 / 999 
625 / 999 
626 / 999 
627 / 999 
628 / 999 
629 / 999 
630 / 999 
631 / 999 
632 / 999 
633 / 999 
634 / 999 
635 / 999 
636 / 999 
637 / 999 
638 / 999 
639 / 999 
640 / 999 
641 / 999 
642 / 999 
643 / 999 
644 / 999 
645 / 999 
646 / 999 
647 / 999 
648 / 999 
649 / 999 
650 / 999 
651 / 999 
652 / 999 
653 / 999 
654 / 999 
655 / 999 
656 / 999 
657 / 999 
658 / 999 
659 / 999 
660 / 999 
661 / 999 
662 / 999 
663 / 999 
664 / 999 
665 / 999 
666 / 999 
667 / 999 
668 / 999 
669 / 999 
670 / 999 
671 / 999 
672 / 999 
673 / 999 
674 / 999 
675 / 999 
676 / 999 
677 / 999 
678 / 999 
679 / 999 
680 / 999 
681 / 999 
682 / 999 
683 / 999 
684 / 999 
685 / 999 
686 / 999 
687 / 999 
688 / 999 
689 / 999 
690 / 999 
691 / 999 
692 / 999 
693 / 999 
694 / 999 
695 / 999 
696 / 999 
697 / 999 
698 / 999 
699 / 999 
700 / 999 
701 / 999 
702 / 999 
703 / 999 
704 / 999 
705 / 999 
706 / 999 
707 / 999 
708 / 999 
709 / 999 
710 / 999 
711 / 999 
712 / 999 
713 / 999 
714 / 999 
715 / 999 
716 / 999 
717 / 999 
718 / 999 
719 / 999 
720 / 999 
721 / 999 
722 / 999 
723 / 999 
724 / 999 
725 / 999 
726 / 999 
727 / 999 
728 / 999 
729 / 999 
730 / 999 
731 / 999 
732 / 999 
733 / 999 
734 / 999 
735 / 999 
736 / 999 
737 / 999 
738 / 999 
739 / 999 
740 / 999 
741 / 999 
742 / 999 
743 / 999 
744 / 999 
745 / 999 
746 / 999 
747 / 999 
748 / 999 
749 / 999 
750 / 999 
751 / 999 
752 / 999 
753 / 999 
754 / 999 
755 / 999 
756 / 999 
757 / 999 
758 / 999 
759 / 999 
760 / 999 
761 / 999 
762 / 999 
763 / 999 
764 / 999 
765 / 999 
766 / 999 
767 / 999 
768 / 999 
769 / 999 
770 / 999 
771 / 999 
772 / 999 
773 / 999 
774 / 999 
775 / 999 
776 / 999 
777 / 999 
778 / 999 
779 / 999 
780 / 999 
781 / 999 
782 / 999 
783 / 999 
784 / 999 
785 / 999 
786 / 999 
787 / 999 
788 / 999 
789 / 999 
790 / 999 
791 / 999 
792 / 999 
793 / 999 
794 / 999 
795 / 999 
796 / 999 
797 / 999 
798 / 999 
799 / 999 
800 / 999 
801 / 999 
802 / 999 
803 / 999 
804 / 999 
805 / 999 
806 / 999 
807 / 999 
808 / 999 
809 / 999 
810 / 999 
811 / 999 
812 / 999 
813 / 999 
814 / 999 
815 / 999 
816 / 999 
817 / 999 
818 / 999 
819 / 999 
820 / 999 
821 / 999 
822 / 999 
823 / 999 
824 / 999 
825 / 999 
826 / 999 
827 / 999 
828 / 999 
829 / 999 
830 / 999 
831 / 999 
832 / 999 
833 / 999 
834 / 999 
835 / 999 
836 / 999 
837 / 999 
838 / 999 
839 / 999 
840 / 999 
841 / 999 
842 / 999 
843 / 999 
844 / 999 
845 / 999 
846 / 999 
847 / 999 
848 / 999 
849 / 999 
850 / 999 
851 / 999 
852 / 999 
853 / 999 
854 / 999 
855 / 999 
856 / 999 
857 / 999 
858 / 999 
859 / 999 
860 / 999 
861 / 999 
862 / 999 
863 / 999 
864 / 999 
865 / 999 
866 / 999 
867 / 999 
868 / 999 
869 / 999 
870 / 999 
871 / 999 
872 / 999 
873 / 999 
874 / 999 
875 / 999 
876 / 999 
877 / 999 
878 / 999 
879 / 999 
880 / 999 
881 / 999 
882 / 999 
883 / 999 
884 / 999 
885 / 999 
886 / 999 
887 / 999 
888 / 999 
889 / 999 
890 / 999 
891 / 999 
892 / 999 
893 / 999 
894 / 999 
895 / 999 
896 / 999 
897 / 999 
898 / 999 
899 / 999 
900 / 999 
901 / 999 
902 / 999 
903 / 999 
904 / 999 
905 / 999 
906 / 999 
907 / 999 
908 / 999 
909 / 999 
910 / 999 
911 / 999 
912 / 999 
913 / 999 
914 / 999 
915 / 999 
916 / 999 
917 / 999 
918 / 999 
919 / 999 
920 / 999 
921 / 999 
922 / 999 
923 / 999 
924 / 999 
925 / 999 
926 / 999 
927 / 999 
928 / 999 
929 / 999 
930 / 999 
931 / 999 
932 / 999 
933 / 999 
934 / 999 
935 / 999 
936 / 999 
937 / 999 
938 / 999 
939 / 999 
940 / 999 
941 / 999 
942 / 999 
943 / 999 
944 / 999 
945 / 999 
946 / 999 
947 / 999 
948 / 999 
949 / 999 
950 / 999 
951 / 999 
952 / 999 
953 / 999 
954 / 999 
955 / 999 
956 / 999 
957 / 999 
958 / 999 
959 / 999 
960 / 999 
961 / 999 
962 / 999 
963 / 999 
964 / 999 
965 / 999 
966 / 999 
967 / 999 
968 / 999 
969 / 999 
970 / 999 
971 / 999 
972 / 999 
973 / 999 
974 / 999 
975 / 999 
976 / 999 
977 / 999 
978 / 999 
979 / 999 
980 / 999 
981 / 999 
982 / 999 
983 / 999 
984 / 999 
985 / 999 
986 / 999 
987 / 999 
988 / 999 
989 / 999 
990 / 999 
991 / 999 
992 / 999 
993 / 999 
994 / 999 
995 / 999 
996 / 999 
997 / 999 
998 / 999 
999 / 999 
  Intercept       alpha 
579.6761870   0.4551001 
warm = psych_strain_collection %>% filter(ISME_source == "warm host") %>% select(strainID) %>% unlist() %>% unname()
other = psych_strain_collection %>% filter(ISME_source == "other host") %>% select(strainID) %>% unlist() %>% unname()
food = psych_strain_collection %>% filter(ISME_source == "food") %>% select(strainID) %>% unlist() %>% unname()
marine = psych_strain_collection %>% filter(ISME_source == "marine") %>% select(strainID) %>% unlist() %>% unname()
terrestrial = psych_strain_collection %>% filter(ISME_source == "terrestrial") %>% select(strainID) %>% unlist() %>% unname()
allseqsum = rowSums(genes_mat_numbered)
names(allseqsum) = rownames(genes_mat)
allisosum = rowSums(genematrix_binary)
names(allisosum) = rownames(genes_mat)
pangenome_by_isolation_summary = rbind(allseqsum, allisosum)
pangenome_by_isolation_summary = t(pangenome_by_isolation_summary)
pangenome_by_isolation_summary = as.data.frame(pangenome_by_isolation_summary)
pangenome_by_isolation_summary$geneCluster = rownames(pangenome_by_isolation_summary)
pangenome_by_isolation_summary$overall_pan_cat = NA
pangenome_by_isolation_summary$overall_pan_cat[pangenome_by_isolation_summary$allisosum >= 84] <- "core"
pangenome_by_isolation_summary$overall_pan_cat[pangenome_by_isolation_summary$allisosum <= 83 & pangenome_by_isolation_summary$allisosum >= 77] <- "soft core"
pangenome_by_isolation_summary$overall_pan_cat[pangenome_by_isolation_summary$allisosum <= 76 & pangenome_by_isolation_summary$allisosum >= 2 ] <- "shell"
pangenome_by_isolation_summary$overall_pan_cat[pangenome_by_isolation_summary$allisosum == 1 ] <- "cloud"
pangenome_by_isolation_summary$overall_pan_cat = factor(pangenome_by_isolation_summary$overall_pan_cat, 
                                                        levels = c("core", "soft core", "shell", "cloud"))

Figure 3.1 pan-genome rarefaction and categories

(pancategory_count = ggplot(data = pangenome_by_isolation_summary, aes(x = overall_pan_cat)) + 
    geom_bar(stat = 'count') +
    theme_classic()
)

ggarrange(pancategory_count, panrarefaction, align = 'h', widths = c(1, 2))

Figure 3.2 functional analysis of different pan-genome categories

COG_multi_cats = multicog_geneclusters %>% filter(COG2 != "")
#just realized that this does not have every COG cat for every strain, for example there is no COG CAT "B" for frigidicola_056...
#will have to make a new data frame to populate from scratch
COG_multi_cats_separated = data.frame()
for(i in 1:nrow(COG_multi_cats)) {
  gen = COG_multi_cats[i,1]
  cat = COG_multi_cats[i,2]
  COG1 = COG_multi_cats[i,3]
  dummy1 = c(gen, cat, COG1)
  COG_multi_cats_separated = rbind.data.frame(COG_multi_cats_separated, as.character(dummy1), stringsAsFactors = F)
  COG2 = COG_multi_cats[i,4]
  dummy2 = c(gen, cat, COG2)
  COG_multi_cats_separated = rbind.data.frame(COG_multi_cats_separated, as.character(dummy2), stringsAsFactors = F)
  COG3 = COG_multi_cats[i,5]
  if (COG3 != ""){
    dummy3 = c(gen, cat, COG3)
    COG_multi_cats_separated = rbind.data.frame(COG_multi_cats_separated, as.character(dummy3), stringsAsFactors = F)
  }
  COG4 = COG_multi_cats[i,6]
  if (COG4 != ""){
    dummy4 = c(gen, cat, COG4)
    COG_multi_cats_separated = rbind.data.frame(COG_multi_cats_separated, as.character(dummy4), stringsAsFactors = F)
  }
}
colnames(COG_multi_cats_separated) = c("geneCluster", "pan_category", "COG_category")
COG_single_cats = multicog_geneclusters %>% filter(COG2 == "") %>%
  select(geneCluster, pan_category, COG1)
colnames(COG_single_cats)[3] = "COG_category"
multiCOG_genes_corrected = rbind(COG_multi_cats_separated, COG_single_cats)
multiCOG_genes_corrected$pan_category = factor(multiCOG_genes_corrected$pan_category, 
                                               levels = c("core", "softcore", "shell", "cloud"))
multiCOG_genes_corrected$COG_category = 
  factor(multiCOG_genes_corrected$COG_category, levels = c("D", "M", "N", "O", "T", "U", "V", "W", "Z",
                                                "A", "B","J", "K", "L","C", "E", "F", "G", "H", "I", "P", "Q",
                                                "S", "X"))
COGcols = c("#72300C", "#93074D", "#D60D69", "#ED5FA6", "#CE1B13", "#A50505", "#E5530A", "#E2770C", "#F9A138", 
         "#F7F072", "#F7D239", "#CCF43B", "#5BB73D", "#057F28", 
         "#05541A", "#20998B", "#60B1F4", "#1458F2", "#5141AF", "#1F048E", "#310872", "#520775", 
         "#9F9FA0", "#39383A")
(function_pancat = ggplot(data = multiCOG_genes_corrected, 
                          aes(x = pan_category, fill = COG_category)) + 
    geom_bar(stat = 'count', position = 'fill') + 
    scale_fill_manual(values = COGcols) +
    theme_classic())

COG_pancat_chi = chisq.test(t(table(multiCOG_genes_corrected$pan_category, multiCOG_genes_corrected$COG_category)))
Chi-squared approximation may be incorrect
COG_pancat_chi

    Pearson's Chi-squared test

data:  t(table(multiCOG_genes_corrected$pan_category, multiCOG_genes_corrected$COG_category))
X-squared = 2748, df = 69, p-value < 2.2e-16
COG_pancat_cor = corrplot(COG_pancat_chi$residuals, is.cor = FALSE)

#add function_pancat and COG_pancat_cor together in Illustrator

Figure 3.3 and stats comparisons - proportion of genome devoted to each pan genome category

psych_PCAT = left_join(psych_PCAT, pangenome_by_isolation_summary[,3:4])
Joining, by = "geneCluster"
test = left_join(psych_PCAT[,c(2:4,33)], psych_strain_collection[,c(3,27)])
Joining, by = "strainID"
test2 = as.data.frame(table(test$strainID, test$overall_pan_cat))
colnames(test2) = c("strainID", "pan_cat", "frequency")
test2 = left_join(test2, psych_strain_collection[,c(3,27)])
Joining, by = "strainID"
number_genes_perstrain = as.data.frame(table(psych_PCAT$strainID))
colnames(number_genes_perstrain) = c("strainID", "num_genes")
test2 = left_join(test2, number_genes_perstrain)
Joining, by = "strainID"
test2$ISME_source[test2$strainID == "P_sp_IAM12030_72-O-c"] <- "terrestrial"
agg_pancat_byiso_bygenome = aggregate(test2$frequency, by = list(test2$ISME_source, test2$pan_cat), FUN = mean)
colnames(agg_pancat_byiso_bygenome) = c("isolation_source", "pan_cat", "average_geneclusters_pergenome")
agg_pancat_byiso_bygenome$pan_cat = factor(agg_pancat_byiso_bygenome$pan_cat, levels = c("core", "soft core", "shell", "cloud"))
agg_pancat_byiso_bygenome_sp = spread(agg_pancat_byiso_bygenome, key = pan_cat, value = average_geneclusters_pergenome)
chisq_pan_iso = chisq.test(agg_pancat_byiso_bygenome_sp[1:5,2:5])
corrplot(chisq_pan_iso$residuals, is.corr = F)

aggregate(test2$frequency, by = list(test2$pan_cat), FUN = mean)
    Group.1          x
1      core 1148.48235
2 soft core  449.64706
3     shell 1004.58824
4     cloud   70.36471
pancat_byiso_bygenome = as.data.frame(table(psych_PCAT$strainID, psych_PCAT$overall_pan_cat))
colnames(pancat_byiso_bygenome) = c("strainID", "pan_cat", "frequency")
pancat_byiso_bygenome = left_join(pancat_byiso_bygenome, psych_strain_collection[,c(3,27)])
Joining, by = "strainID"
pancat_byiso_bygenome = left_join(pancat_byiso_bygenome, number_genes_perstrain)
Joining, by = "strainID"
  
pancat_byiso_bygenome$ISME_source = factor(pancat_byiso_bygenome$ISME_source, 
                                           levels = c("warm host", "other host", "food", "marine", "terrestrial"))
pancat_byiso_bygenome$pan_cat = factor(pancat_byiso_bygenome$pan_cat, 
                                           levels = c("core", "soft core", "shell", "cloud"))
pancat_byiso_bygenome$ISME_source[pancat_byiso_bygenome$strainID == "P_sp_IAM12030_72-O-c"] <- "terrestrial"
pancat_byiso_bygenome_sp = spread(pancat_byiso_bygenome, key = "pan_cat", value = "frequency")
pancat_byiso_bygenome_sp$core_prop = pancat_byiso_bygenome_sp$core/pancat_byiso_bygenome_sp$num_genes
pancat_byiso_bygenome_sp$softcore_prop = pancat_byiso_bygenome_sp$`soft core`/pancat_byiso_bygenome_sp$num_genes
pancat_byiso_bygenome_sp$shell_prop = pancat_byiso_bygenome_sp$shell/pancat_byiso_bygenome_sp$num_genes
pancat_byiso_bygenome_sp$cloud_prop = pancat_byiso_bygenome_sp$cloud/pancat_byiso_bygenome_sp$num_genes
pancat_byiso_bygenome_ga = pancat_byiso_bygenome_sp %>% 
  gather(core_prop, softcore_prop, shell_prop, cloud_prop, key = "pan_cat", value = "proportion") %>%
  select(-core, -`soft core`, -shell, -cloud)
pancat_byiso_bygenome_ga$pan_cat = str_remove(pancat_byiso_bygenome_ga$pan_cat, "_prop")
pancat_byiso_bygenome_ga$pan_cat = factor(pancat_byiso_bygenome_ga$pan_cat, 
                                          levels = c("core", "softcore", "shell", "cloud"))
(genenum_iso = ggplot(data = pancat_byiso_bygenome_ga, aes(x = ISME_source, y= num_genes, color = ISME_source)) + 
  geom_boxplot(alpha = 0) + 
  geom_point(position=position_dodge(width=0.75),aes(group=ISME_source)) +
  scale_color_manual(values = ISMEcolors) +
  #facet_grid(.~pan_cat, scales = "free") +
  theme_classic())

(pan_str_iso = ggplot(data = pancat_byiso_bygenome_ga, aes(x = ISME_source, y= proportion, color = ISME_source)) + 
  geom_boxplot(alpha = 0) + 
  geom_point(position=position_dodge(width=0.75),aes(group=ISME_source)) +
  scale_color_manual(values = ISMEcolors) +
  facet_grid(.~pan_cat, scales = "free") +
  theme_classic())

stats_core = pancat_byiso_bygenome_ga %>% filter(pan_cat == 'core')
kruskal.test(proportion ~ ISME_source, data = stats_core)

    Kruskal-Wallis rank sum test

data:  proportion by ISME_source
Kruskal-Wallis chi-squared = 18.442, df = 4, p-value = 0.001011
pairwise.wilcox.test(x = stats_core$proportion, g = stats_core$ISME_source, p.adjust.method = 'BH')

    Pairwise comparisons using Wilcoxon rank sum test 

data:  stats_core$proportion and stats_core$ISME_source 

            warm host other host food  marine
other host  0.013     -          -     -     
food        0.013     0.918      -     -     
marine      0.738     0.022      0.023 -     
terrestrial 0.918     0.013      0.014 0.745 

P value adjustment method: BH 
aggregate(stats_core$proportion, by = list(stats_core$ISME_source), FUN = median)
      Group.1         x
1   warm host 0.4424822
2  other host 0.4151218
3        food 0.4139804
4      marine 0.4430722
5 terrestrial 0.4381671
stats_softcore = pancat_byiso_bygenome_ga %>% filter(pan_cat == 'softcore')
kruskal.test(proportion ~ ISME_source, data = stats_softcore)

    Kruskal-Wallis rank sum test

data:  proportion by ISME_source
Kruskal-Wallis chi-squared = 12.696, df = 4, p-value = 0.01286
pairwise.wilcox.test(x = stats_softcore$proportion, g = stats_softcore$ISME_source, p.adjust.method = 'BH')

    Pairwise comparisons using Wilcoxon rank sum test 

data:  stats_softcore$proportion and stats_softcore$ISME_source 

            warm host other host food  marine
other host  0.386     -          -     -     
food        0.868     0.407      -     -     
marine      0.143     0.144      0.094 -     
terrestrial 0.065     0.065      0.033 0.868 

P value adjustment method: BH 
aggregate(stats_softcore$proportion, by = list(stats_softcore$ISME_source), FUN = median)
      Group.1         x
1   warm host 0.1645282
2  other host 0.1670198
3        food 0.1651576
4      marine 0.1757599
5 terrestrial 0.1745093
stats_shell = pancat_byiso_bygenome_ga %>% filter(pan_cat == 'shell')
kruskal.test(proportion ~ ISME_source, data = stats_shell)

    Kruskal-Wallis rank sum test

data:  proportion by ISME_source
Kruskal-Wallis chi-squared = 17.722, df = 4, p-value = 0.001398
pairwise.wilcox.test(x = stats_shell$proportion, g = stats_shell$ISME_source, p.adjust.method = 'BH')
cannot compute exact p-value with ties

    Pairwise comparisons using Wilcoxon rank sum test 

data:  stats_shell$proportion and stats_shell$ISME_source 

            warm host other host food  marine
other host  0.023     -          -     -     
food        0.035     0.984      -     -     
marine      0.984     0.013      0.034 -     
terrestrial 0.984     0.020      0.034 0.984 

P value adjustment method: BH 
aggregate(stats_shell$proportion, by = list(stats_shell$ISME_source), FUN = median)
      Group.1         x
1   warm host 0.3662383
2  other host 0.4024303
3        food 0.3940601
4      marine 0.3621622
5 terrestrial 0.3669571
stats_cloud = pancat_byiso_bygenome_ga %>% filter(pan_cat == 'cloud')
kruskal.test(proportion ~ ISME_source, data = stats_cloud)

    Kruskal-Wallis rank sum test

data:  proportion by ISME_source
Kruskal-Wallis chi-squared = 7.691, df = 4, p-value = 0.1036
pairwise.wilcox.test(x = stats_cloud$proportion, g = stats_cloud$ISME_source, p.adjust.method = 'BH')
cannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with ties

    Pairwise comparisons using Wilcoxon rank sum test 

data:  stats_cloud$proportion and stats_cloud$ISME_source 

            warm host other host food marine
other host  0.20      -          -    -     
food        0.87      0.20       -    -     
marine      0.96      0.21       0.65 -     
terrestrial 0.96      0.27       0.65 0.96  

P value adjustment method: BH 
aggregate(stats_cloud$proportion, by = list(stats_cloud$ISME_source), FUN = median)
      Group.1          x
1   warm host 0.01546329
2  other host 0.01047651
3        food 0.02462527
4      marine 0.01698842
5 terrestrial 0.02118343

Figure 3.4 unique gene content between isolation sources

warm = psych_strain_collection %>% filter(ISME_source == "warm host") %>% select(strainID) %>% unlist() %>% unname()
other = psych_strain_collection %>% filter(ISME_source == "other host") %>% select(strainID) %>% unlist() %>% unname()
food = psych_strain_collection %>% filter(ISME_source == "food") %>% select(strainID) %>% unlist() %>% unname()
marine = psych_strain_collection %>% filter(ISME_source == "marine") %>% select(strainID) %>% unlist() %>% unname()
terrestrial = psych_strain_collection %>% filter(ISME_source == "terrestrial") %>% select(strainID) %>% unlist() %>% unname()
warmseqsum = rowSums(genes_mat_numbered[,colnames(genes_mat_numbered) %in% warm])
names(warmseqsum) = rownames(genes_mat)
warmisosum = rowSums(genematrix_binary[,colnames(genematrix_binary) %in% warm])
names(warmisosum) = rownames(genes_mat)
otherseqsum = rowSums(genes_mat_numbered[,colnames(genes_mat_numbered) %in% other])
names(otherseqsum) = rownames(genes_mat)
otherisosum = rowSums(genematrix_binary[,colnames(genematrix_binary) %in% other])
names(otherisosum) = rownames(genes_mat)
foodseqsum = rowSums(genes_mat_numbered[,colnames(genes_mat_numbered) %in% food])
names(otherseqsum) = rownames(genes_mat)
foodisosum = rowSums(genematrix_binary[,colnames(genematrix_binary) %in% food])
names(foodisosum) = rownames(genes_mat)
marineseqsum = rowSums(genes_mat_numbered[,colnames(genes_mat_numbered) %in% marine])
names(marineseqsum) = rownames(genes_mat)
marineisosum = rowSums(genematrix_binary[,colnames(genematrix_binary) %in% marine])
names(marineisosum) = rownames(genes_mat)
terrestrialseqsum = rowSums(genes_mat_numbered[,colnames(genes_mat_numbered) %in% terrestrial])
names(terrestrialseqsum) = rownames(genes_mat)
terrestrialisosum = rowSums(genematrix_binary[,colnames(genematrix_binary) %in% terrestrial])
names(terrestrialisosum) = rownames(genes_mat)
allseqsum = rowSums(genes_mat_numbered)
names(allseqsum) = rownames(genes_mat)
allisosum = rowSums(genematrix_binary)
names(allisosum) = rownames(genes_mat)
pan_str_iso = rbind(allseqsum, allisosum, warmseqsum, warmisosum, otherseqsum, otherisosum, 
                                       foodseqsum, foodisosum, marineseqsum, marineisosum, terrestrialseqsum, terrestrialisosum)
pan_str_iso = t(pan_str_iso)
pan_str_iso = as.data.frame(pan_str_iso)
pan_str_iso$geneCluster = rownames(pan_str_iso)
pan_str_iso$overall_pan_cat = NA
pan_str_iso$overall_pan_cat[pan_str_iso$allisosum >= 84] <- "core"
pan_str_iso$overall_pan_cat[pan_str_iso$allisosum <= 83 & pan_str_iso$allisosum >= 77] <- "soft core"
pan_str_iso$overall_pan_cat[pan_str_iso$allisosum <= 82 & pan_str_iso$allisosum >= 2 ] <- "shell"
pan_str_iso$overall_pan_cat[pan_str_iso$allisosum == 1 ] <- "cloud"
pan_str_iso$warm_pan_cat = NA
pan_str_iso$warm_pan_cat[pan_str_iso$warmisosum >= 13] <- "core"
pan_str_iso$warm_pan_cat[pan_str_iso$warmisosum <= 12 & pan_str_iso$warmisosum >= 2 ] <- "shell"
pan_str_iso$warm_pan_cat[pan_str_iso$warmisosum == 1 ] <- "cloud"
pan_str_iso$warm_pan_cat[pan_str_iso$warmisosum == 0 ] <- "absent"
pan_str_iso$other_pan_cat = NA
pan_str_iso$other_pan_cat[pan_str_iso$otherisosum >= 20] <- "core"
pan_str_iso$other_pan_cat[pan_str_iso$otherisosum <= 19 & pan_str_iso$otherisosum >= 2 ] <- "shell"
pan_str_iso$other_pan_cat[pan_str_iso$otherisosum == 1 ] <- "cloud"
pan_str_iso$other_pan_cat[pan_str_iso$otherisosum == 0 ] <- "absent"
pan_str_iso$food_pan_cat = NA
pan_str_iso$food_pan_cat[pan_str_iso$foodisosum == 11] <- "core"
pan_str_iso$food_pan_cat[pan_str_iso$foodisosum <= 10 & pan_str_iso$foodisosum >= 2 ] <- "shell"
pan_str_iso$food_pan_cat[pan_str_iso$foodisosum == 1 ] <- "cloud"
pan_str_iso$food_pan_cat[pan_str_iso$foodisosum == 0 ] <- "absent"
pan_str_iso$marine_pan_cat = NA
pan_str_iso$marine_pan_cat[pan_str_iso$marineisosum >= 19] <- "core"
pan_str_iso$marine_pan_cat[pan_str_iso$marineisosum <= 18 & pan_str_iso$marineisosum >= 2 ] <- "shell"
pan_str_iso$marine_pan_cat[pan_str_iso$marineisosum == 1 ] <- "cloud"
pan_str_iso$marine_pan_cat[pan_str_iso$marineisosum == 0 ] <- "absent"
pan_str_iso$terrestrial_pan_cat = NA
pan_str_iso$terrestrial_pan_cat[pan_str_iso$terrestrialisosum >= 15] <- "core"
pan_str_iso$terrestrial_pan_cat[pan_str_iso$terrestrialisosum <= 14 & pan_str_iso$terrestrialisosum >= 2 ] <- "shell"
pan_str_iso$terrestrial_pan_cat[pan_str_iso$terrestrialisosum == 1 ] <- "cloud"
pan_str_iso$terrestrial_pan_cat[pan_str_iso$terrestrialisosum == 0 ] <- "absent"
unique_warm = pan_str_iso %>% filter(warm_pan_cat != "absent" & other_pan_cat == "absent" & food_pan_cat == "absent" & marine_pan_cat == "absent" & terrestrial_pan_cat == "absent") %>% select(geneCluster) %>% unlist() %>% unname
unique_warm_annot = multiCOG_genes_corrected %>% filter(geneCluster %in% unique_warm)
unique_warm_annot$isolation = "warm"
unique_other = pan_str_iso %>% filter(warm_pan_cat == "absent" & other_pan_cat != "absent" & food_pan_cat == "absent" & marine_pan_cat == "absent" & terrestrial_pan_cat == "absent") %>% select(geneCluster) %>% unlist() %>% unname
unique_other_annot = multiCOG_genes_corrected %>% filter(geneCluster %in% unique_other)
unique_other_annot$isolation = "other"
unique_food = pan_str_iso %>% filter(warm_pan_cat == "absent" & other_pan_cat == "absent" & food_pan_cat != "absent" & marine_pan_cat == "absent" & terrestrial_pan_cat == "absent") %>% select(geneCluster) %>% unlist() %>% unname
unique_food_annot = multiCOG_genes_corrected %>% filter(geneCluster %in% unique_food)
unique_food_annot$isolation = "food"
unique_marine = pan_str_iso %>% filter(warm_pan_cat == "absent" & other_pan_cat == "absent" & food_pan_cat == "absent" & marine_pan_cat != "absent" & terrestrial_pan_cat == "absent") %>% select(geneCluster) %>% unlist() %>% unname
unique_marine_annot = multiCOG_genes_corrected %>% filter(geneCluster %in% unique_marine)
unique_marine_annot$isolation = "marine"
unique_terrestrial = pan_str_iso %>% filter(warm_pan_cat == "absent" & other_pan_cat == "absent" & food_pan_cat == "absent" & marine_pan_cat == "absent" & terrestrial_pan_cat != "absent") %>% select(geneCluster) %>% unlist() %>% unname
unique_terrestrial_annot = multiCOG_genes_corrected %>% filter(geneCluster %in% unique_terrestrial)
unique_terrestrial_annot$isolation = "terrestrial"
unique_genes_per_isolation = rbind(unique_warm_annot, unique_other_annot, unique_food_annot, unique_marine_annot, unique_terrestrial_annot)
unique_genes_per_isolation$isolation = factor(unique_genes_per_isolation$isolation, levels = c("warm", "other", "food", "marine", "terrestrial"))
unique_genes_per_isolation$COG_category = factor(unique_genes_per_isolation$COG_category, levels = c("D", "M", "N", "O", "T", "U", "V", "W", "Z",
                                                                                 "A", "B","J", "K", "L",
                                                                                 "C", "E", "F", "G", "H", "I", "P", "Q",
                                                                                 "S", "X"))
cols = c("#72300C", "#93074D", "#D60D69", "#ED5FA6", "#CE1B13", "#A50505",
         "#E5530A", "#E2770C", "#F9A138", "#F7F072", "#F7D239", "#CCF43B",
         "#5BB73D", "#057F28", "#05541A", "#20998B", "#60B1F4", "#1458F2",
         "#5141AF", "#1F048E", "#310872", "#520775", "#9F9FA0", "#39383A")
(unique_gene_content = ggplot(data = unique_genes_per_isolation, aes(x = isolation, fill = COG_category)) +
  geom_bar(stat = 'count') +
  scale_fill_manual(values = cols) +
  theme_classic())

unique_corr = table(unique_genes_per_isolation$isolation, unique_genes_per_isolation$COG_category)
chisq_uni_iso = chisq.test(unique_corr)
Chi-squared approximation may be incorrect
corrplot(chisq_uni_iso$residuals, is.corr = F)

#add unique_gene_content w corrplot in illustrator

Pan-genome wide association study with isolation source as trait.

unique(psych_strain_collection$ISME_source)
[1] "marine"      "food"        "terrestrial" "warm host"   "other host" 
isolationsource = psych_strain_collection[,c(3,27)]
isolationsource$dummy = 1
isolationsource = isolationsource %>%
  spread(key = ISME_source, value = dummy)
isolationsource[is.na(isolationsource)] <- 0
rownames(isolationsource) = isolationsource$strainID
WH <- as.vector(unlist(isolationsource$`warm host`))
names(WH) = rownames(isolationsource)
all(names(WH) %in% rownames(genematrix_treewas))
[1] TRUE
all(rownames(genematrix_treewas) %in% names(WH))
[1] TRUE
WH_treewas <- treeWAS(snps = genematrix_treewas, phen = WH, tree = P.tree.noout, seed = 1)
[1] "treeWAS snps sim done @ 2021-03-24 10:11:57"
[1] "Reconstructions completed @ 2021-03-24 10:12:10"
[1] "Started running terminal test @ 2021-03-24 10:12:10"
[1] "Real data scores completed for terminal test @ 2021-03-24 10:12:10"
[1] "Simulated data scores completed for terminal test @ 2021-03-24 10:12:10"
[1] "Started running simultaneous test @ 2021-03-24 10:12:10"
[1] "Real data scores completed for simultaneous test @ 2021-03-24 10:12:10"
[1] "Simulated data scores completed for simultaneous test @ 2021-03-24 10:12:11"
[1] "Started running subsequent test @ 2021-03-24 10:12:11"
[1] "Real data scores completed for subsequent test @ 2021-03-24 10:12:11"
[1] "Simulated data scores completed for subsequent test @ 2021-03-24 10:12:11"
[1] "Finished running terminal test @ 2021-03-24 10:12:12"
[1] "Finished running simultaneous test @ 2021-03-24 10:12:12"
[1] "Finished running subsequent test @ 2021-03-24 10:12:12"
[1] "ID of significant loci completed @ 2021-03-24 10:12:12"

print(WH_treewas)
    #################### 
    ## treeWAS output ## 
    #################### 
     
    #################### 
    ## All findings:  ## 
    #################### 
Number of significant loci: [1] 0
     
    ######################## 
    ## Findings by test:  ## 
    ######################## 
     ####################  
     ##  terminal test ## 
     ####################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
0.8588235 
     ########################  
     ##  simultaneous test ## 
     ########################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
      4.5 
     ######################  
     ##  subsequent test ## 
     ######################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
 159.3333 
OH <- as.vector(unlist(isolationsource$`other host`))
names(OH) = rownames(isolationsource)
all(names(OH) %in% rownames(genematrix_treewas))
[1] TRUE
all(rownames(genematrix_treewas) %in% names(OH))
[1] TRUE
OH_treewas <- treeWAS(snps = genematrix_treewas, phen = OH, tree = P.tree.noout, seed = 1)
[1] "treeWAS snps sim done @ 2021-03-24 10:12:20"
[1] "Reconstructions completed @ 2021-03-24 10:12:31"
[1] "Started running terminal test @ 2021-03-24 10:12:31"
[1] "Real data scores completed for terminal test @ 2021-03-24 10:12:31"
[1] "Simulated data scores completed for terminal test @ 2021-03-24 10:12:32"
[1] "Started running simultaneous test @ 2021-03-24 10:12:32"
[1] "Real data scores completed for simultaneous test @ 2021-03-24 10:12:32"
[1] "Simulated data scores completed for simultaneous test @ 2021-03-24 10:12:32"
[1] "Started running subsequent test @ 2021-03-24 10:12:32"
[1] "Real data scores completed for subsequent test @ 2021-03-24 10:12:33"
[1] "Simulated data scores completed for subsequent test @ 2021-03-24 10:12:33"
[1] "Finished running terminal test @ 2021-03-24 10:12:33"
[1] "Finished running simultaneous test @ 2021-03-24 10:12:33"
[1] "Finished running subsequent test @ 2021-03-24 10:12:34"
[1] "ID of significant loci completed @ 2021-03-24 10:12:34"

print(OH_treewas)
    #################### 
    ## treeWAS output ## 
    #################### 
     
    #################### 
    ## All findings:  ## 
    #################### 
Number of significant loci: [1] 5
Significant loci: 
[1] "GC00002129_r1_3" "GC00002231_r1_1" "GC00002376"      "GC00002380_r1_2"
[5] "GC00002622"     
     
    ######################## 
    ## Findings by test:  ## 
    ######################## 
     ####################  
     ##  terminal test ## 
     ####################  
Number of significant loci: 
[1] 1
Significance threshold: 
99.99997% 
0.6235294 
Significant loci: 
           SNP.locus p.value     score G1P1 G0P0 G1P0 G0P1
GC00002622      6994       0 0.6705882   11   60    2   12
     ########################  
     ##  simultaneous test ## 
     ########################  
Number of significant loci: 
[1] 4
Significance threshold: 
99.99997% 
        4 
Significant loci: 
                SNP.locus p.value score G1P1 G0P0 G1P0 G0P1
GC00002129_r1_3      5957       0     6    9   56    6   14
GC00002231_r1_1      6198       0     5   11   53    9   12
GC00002376           6521       0     5    6   52   10   17
GC00002380_r1_2      6531       0     6   10   56    6   13
     ######################  
     ##  subsequent test ## 
     ######################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
 138.2667 
Fo <- as.vector(unlist(isolationsource$food))
names(Fo) = rownames(isolationsource)
all(names(Fo) %in% rownames(genematrix_treewas))
[1] TRUE
all(rownames(genematrix_treewas) %in% names(Fo))
[1] TRUE
Fo_treewas <- treeWAS(snps = genematrix_treewas, phen = Fo, tree = P.tree.noout, seed = 1)
[1] "treeWAS snps sim done @ 2021-03-24 10:12:41"
[1] "Reconstructions completed @ 2021-03-24 10:12:53"
[1] "Started running terminal test @ 2021-03-24 10:12:53"
[1] "Real data scores completed for terminal test @ 2021-03-24 10:12:53"
[1] "Simulated data scores completed for terminal test @ 2021-03-24 10:12:54"
[1] "Started running simultaneous test @ 2021-03-24 10:12:54"
[1] "Real data scores completed for simultaneous test @ 2021-03-24 10:12:54"
[1] "Simulated data scores completed for simultaneous test @ 2021-03-24 10:12:54"
[1] "Started running subsequent test @ 2021-03-24 10:12:54"
[1] "Real data scores completed for subsequent test @ 2021-03-24 10:12:54"
[1] "Simulated data scores completed for subsequent test @ 2021-03-24 10:12:54"
[1] "Finished running terminal test @ 2021-03-24 10:12:55"
[1] "Finished running simultaneous test @ 2021-03-24 10:12:55"
[1] "Finished running subsequent test @ 2021-03-24 10:12:55"
[1] "ID of significant loci completed @ 2021-03-24 10:12:55"

print(Fo_treewas)
    #################### 
    ## treeWAS output ## 
    #################### 
     
    #################### 
    ## All findings:  ## 
    #################### 
Number of significant loci: [1] 5
Significant loci: 
[1] "GC00000256_r1_r1_1_p1" "GC00002564"            "GC00002565"           
[4] "GC00002566"            "GC00002666"           
     
    ######################## 
    ## Findings by test:  ## 
    ######################## 
     ####################  
     ##  terminal test ## 
     ####################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
0.8580392 
     ########################  
     ##  simultaneous test ## 
     ########################  
Number of significant loci: 
[1] 5
Significance threshold: 
99.99997% 
 4.966667 
Significant loci: 
                      SNP.locus p.value score G1P1 G0P0 G1P0 G0P1
GC00000256_r1_r1_1_p1      1711       0     5    7   53   21    4
GC00002564                 6889       0     5    5   67    7    6
GC00002565                 6890       0     5    5   67    7    6
GC00002566                 6891       0     5    5   67    7    6
GC00002666                 7085       0     5    5   68    6    6
     ######################  
     ##  subsequent test ## 
     ######################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
 159.9889 
Ma <- as.vector(unlist(isolationsource$marine))
names(Ma) = rownames(isolationsource)
all(names(Ma) %in% rownames(genematrix_treewas))
[1] TRUE
all(rownames(genematrix_treewas) %in% names(Ma))
[1] TRUE
Ma_treewas <- treeWAS(snps = genematrix_treewas, phen = Ma, tree = P.tree.noout, seed = 1)
[1] "treeWAS snps sim done @ 2021-03-24 10:13:02"
[1] "Reconstructions completed @ 2021-03-24 10:13:14"
[1] "Started running terminal test @ 2021-03-24 10:13:14"
[1] "Real data scores completed for terminal test @ 2021-03-24 10:13:14"
[1] "Simulated data scores completed for terminal test @ 2021-03-24 10:13:15"
[1] "Started running simultaneous test @ 2021-03-24 10:13:15"
[1] "Real data scores completed for simultaneous test @ 2021-03-24 10:13:15"
[1] "Simulated data scores completed for simultaneous test @ 2021-03-24 10:13:15"
[1] "Started running subsequent test @ 2021-03-24 10:13:15"
[1] "Real data scores completed for subsequent test @ 2021-03-24 10:13:15"
[1] "Simulated data scores completed for subsequent test @ 2021-03-24 10:13:15"
[1] "Finished running terminal test @ 2021-03-24 10:13:16"
[1] "Finished running simultaneous test @ 2021-03-24 10:13:16"
[1] "Finished running subsequent test @ 2021-03-24 10:13:16"
[1] "ID of significant loci completed @ 2021-03-24 10:13:16"

print(Ma_treewas)
    #################### 
    ## treeWAS output ## 
    #################### 
     
    #################### 
    ## All findings:  ## 
    #################### 
Number of significant loci: [1] 4
Significant loci: 
[1] "GC00001426_2" "GC00002047"   "GC00002181_2" "GC00003144"  
     
    ######################## 
    ## Findings by test:  ## 
    ######################## 
     ####################  
     ##  terminal test ## 
     ####################  
Number of significant loci: 
[1] 2
Significance threshold: 
99.99997% 
0.6227451 
Significant loci: 
             SNP.locus p.value      score G1P1 G0P0 G1P0 G0P1
GC00001426_2      4122       0 -0.6235294   15    1   63    6
GC00003144        7862       0  0.6235294    6   63    1   15
     ########################  
     ##  simultaneous test ## 
     ########################  
Number of significant loci: 
[1] 2
Significance threshold: 
99.99997% 
        5 
Significant loci: 
             SNP.locus p.value score G1P1 G0P0 G1P0 G0P1
GC00002047        5782       0    11   13   49   15    8
GC00002181_2      6087       0     8   11   52   12   10
     ######################  
     ##  subsequent test ## 
     ######################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
 143.6667 
Te <- as.vector(unlist(isolationsource$terrestrial))
names(Te) = rownames(isolationsource)
all(names(Te) %in% rownames(genematrix_treewas))
[1] TRUE
all(rownames(genematrix_treewas) %in% names(Te))
[1] TRUE
Te_treewas <- treeWAS(snps = genematrix_treewas, phen = Te, tree = P.tree.noout, seed = 1)
[1] "treeWAS snps sim done @ 2021-03-24 10:13:23"
[1] "Reconstructions completed @ 2021-03-24 10:13:36"
[1] "Started running terminal test @ 2021-03-24 10:13:36"
[1] "Real data scores completed for terminal test @ 2021-03-24 10:13:36"
[1] "Simulated data scores completed for terminal test @ 2021-03-24 10:13:37"
[1] "Started running simultaneous test @ 2021-03-24 10:13:37"
[1] "Real data scores completed for simultaneous test @ 2021-03-24 10:13:37"
[1] "Simulated data scores completed for simultaneous test @ 2021-03-24 10:13:37"
[1] "Started running subsequent test @ 2021-03-24 10:13:37"
[1] "Real data scores completed for subsequent test @ 2021-03-24 10:13:38"
[1] "Simulated data scores completed for subsequent test @ 2021-03-24 10:13:38"
[1] "Finished running terminal test @ 2021-03-24 10:13:38"
[1] "Finished running simultaneous test @ 2021-03-24 10:13:38"
[1] "Finished running subsequent test @ 2021-03-24 10:13:38"
[1] "ID of significant loci completed @ 2021-03-24 10:13:38"

print(Te_treewas)
    #################### 
    ## treeWAS output ## 
    #################### 
     
    #################### 
    ## All findings:  ## 
    #################### 
Number of significant loci: [1] 1
Significant loci: 
[1] "GC00000111_6"
     
    ######################## 
    ## Findings by test:  ## 
    ######################## 
     ####################  
     ##  terminal test ## 
     ####################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
0.7647059 
     ########################  
     ##  simultaneous test ## 
     ########################  
Number of significant loci: 
[1] 1
Significance threshold: 
99.99997% 
 4.966667 
Significant loci: 
             SNP.locus p.value score G1P1 G0P0 G1P0 G0P1
GC00000111_6      1141       0    -5    6   15   54   10
     ######################  
     ##  subsequent test ## 
     ######################  
Number of significant loci: 
[1] 0
Significance threshold: 
99.99997% 
 153.6667 
OH_treewas_gc = OH_treewas$treeWAS.combined$treeWAS.combined %>% unlist()
OH_treewas_annotated = psych_eggnog_annotations %>% filter(geneCluster %in% OH_treewas_gc)
Fo_treewas_gc = Fo_treewas$treeWAS.combined$treeWAS.combined %>% unlist()
Fo_treewas_annotated = psych_eggnog_annotations %>% filter(geneCluster %in% Fo_treewas_gc)
Ma_treewas_gc = Ma_treewas$treeWAS.combined$treeWAS.combined %>% unlist()
Ma_treewas_annotated = psych_eggnog_annotations %>% filter(geneCluster %in% Ma_treewas_gc)
Te_treewas_gc = Te_treewas$treeWAS.combined$treeWAS.combined %>% unlist()
Te_treewas_annotated = psych_eggnog_annotations %>% filter(geneCluster %in% Te_treewas_gc)

Isolation source ancestral character estimation.

#two state ancestral state reconstruction
ordered_df = strain_collection[match(M.tree$tip.label, strain_collection$strainID),]
rownames(ordered_df) = ordered_df$strainID
x1<-setNames(ordered_df[,21],rownames(ordered_df))
x1col = c("deepskyblue3", "orange")
fitER1 = ace(x1, M.tree, model = "ER", type = "discrete", marginal = TRUE)
fitSYM1 = ace(x1, M.tree, model = "SYM", type = "discrete", marginal = TRUE)
fitARD1 = ace(x1, M.tree, model = "ARD", type = "discrete", marginal = TRUE)
#ARD model maximizes likelihood, but does it do so significantly?
1 - pchisq(2*abs(fitARD1$loglik - fitER1$loglik), 1) #p = 0.15
[1] 0.1544003
1 - pchisq(2*abs(fitARD1$loglik - fitSYM1$loglik), 1) #p = 0.15
[1] 0.1544003
#ok, so is there a difference between ER and SYM?
1 - pchisq(2*abs(fitER1$loglik - fitSYM1$loglik), 1)
[1] 1
#no
#so I will go with the simplest ER model
plotTree(M.tree,fsize=0.8,ftype="i")
nodelabels(node=1:M.tree$Nnode+Ntip(M.tree),pie=fitER1$lik.anc,piecol = x1col,cex=0.5)
#tiplabels(pie=to.matrix(x1[M.tree$tip.label],levels(x1)),piecol = x1col,cex=0.3)
#add.simmap.legend(leg=sort(unique(x1)),colors=x1col,x=0.9*par()$usr[1],
#                  y=-max(nodeHeights(M.tree)),fsize=0.8)
#plotTree(M.tree,fsize=0.8,ftype="i")
tiplabels(pie=to.matrix(x1,sort(unique(x1))),piecol=x1col,cex=0.3)
add.simmap.legend(colors=x1col,prompt=FALSE,x=0.9*par()$usr[1],
                  y=-max(nodeHeights(M.tree)),fsize=0.8)

fitER1

    Ancestral Character Estimation

Call: ace(x = x1, phy = M.tree, type = "discrete", model = "ER", marginal = TRUE)

    Log-likelihood: -39.5478 

Rate index matrix:
  c w
c . 1
w 1 .

Parameter estimates:
 rate index estimate std-err
          1   1.4862  0.4245

Scaled likelihoods at the root (type '...$lik.anc' to get them for all nodes):
        c         w 
0.1730664 0.8269336 
psychroot = drop.tip(M.tree, c("M_boevrei","M_atlantae","M_osloensis","A_puyangensis",
                     "M_cuniculi","M_porci","M_pluranimalium","M_canis","M_catarrhalis","M_caviae",
                     "M_ovis","M_bovoculi","M_oblonga","M_equi","M_bovis","M_caprae","M_lacunata","M_nonliquefaciens"))
x1psychroot<-x1[names(x1) %in% psychroot$tip.label]
fitER_psychroot = ace(x1psychroot, psychroot, model = "ER", type = "discrete", marginal = TRUE)
fitER_psychroot

    Ancestral Character Estimation

Call: ace(x = x1psychroot, phy = psychroot, type = "discrete", model = "ER", 
    marginal = TRUE)

    Log-likelihood: -32.31518 

Rate index matrix:
  c w
c . 1
w 1 .

Parameter estimates:
 rate index estimate std-err
          1   2.7609  0.7641

Scaled likelihoods at the root (type '...$lik.anc' to get them for all nodes):
        c         w 
0.4464888 0.5535112 
plotTree(psychroot,fsize=0.8,ftype="i")
nodelabels(node=1:psychroot$Nnode+Ntip(psychroot),pie=fitER_psychroot$lik.anc,piecol = x1col,cex=0.5)
#tiplabels(pie=to.matrix(x1psychroot[psychroot$tip.label],levels(x1psychroot)),piecol = x1col,cex=0.3)
#add.simmap.legend(leg=sort(unique(x1psychroot)),colors=x1col,x=0.9*par()$usr[1],
#                  y=-max(nodeHeights(psychroot)),fsize=0.8)
#plotTree(M.tree,fsize=0.8,ftype="i")
tiplabels(pie=to.matrix(x1psychroot,sort(unique(x1psychroot))),piecol=x1col,cex=0.3)
add.simmap.legend(colors=x1col,prompt=FALSE,x=0.9*par()$usr[1],
                  y=-max(nodeHeights(psychroot)),fsize=0.8)

#now by more specific isolation sources 
ordered_df$ISME_source = factor(ordered_df$ISME_source,
                                levels = c("warm host", "other host", "food", "marine", "terrestrial"))
x2<-setNames(ordered_df[,19],rownames(ordered_df))
x2col = c("#F9D503", "#5DC863", "#21908C", "#3B528B", "#440154")
fitER2 = ace(x2, M.tree, model = "ER", type = "discrete", marginal = TRUE)
fitSYM2 = ace(x2, M.tree, model = "SYM", type = "discrete", marginal = TRUE)
NaNs producedNA/Inf replaced by maximum positive valueNaNs produced
fitARD2 = ace(x2, M.tree, model = "ARD", type = "discrete", marginal = TRUE)
imaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionimaginary parts discarded in coercionNaNs producedNA/Inf replaced by maximum positive valueNaNs produced
#ARD model maximizes likelihood, but does it do so significantly?
1 - pchisq(2*abs(fitARD2$loglik - fitER2$loglik), 1) #p = 1.110223e-15
[1] 1.110223e-15
1 - pchisq(2*abs(fitARD2$loglik - fitSYM2$loglik), 1) #p = 4.260376e-05
[1] 4.260376e-05
#both significant, so
#I will go with the ARD model
1 - pchisq(2*abs(fitSYM2$loglik - fitER2$loglik), 1)
[1] 5.422884e-12
plotTree(M.tree,fsize=0.8,ftype="i")
tiplabels(pie=to.matrix(x2,sort(unique(x2))),piecol=x2col,cex=0.3)
add.simmap.legend(colors=x2col,prompt=FALSE,x=0.9*par()$usr[1],
                  y=-max(nodeHeights(M.tree)),fsize=0.8)
#plotTree(M.tree,fsize=0.8,ftype="i")
nodelabels(node=1:M.tree$Nnode+Ntip(M.tree),pie=fitER2$lik.anc,piecol = x2col,cex=0.5)

#tiplabels(pie=to.matrix(x2[M.tree$tip.label],levels(x2)),piecol = x2col,cex=0.3)
#add.simmap.legend(leg=sort(unique(x2)),colors=x2col,x=0.9*par()$usr[1],
#                  y=-max(nodeHeights(M.tree)),fsize=0.8)
x2psychroot<-x2[names(x2) %in% psychroot$tip.label]
fitER2_psychroot = ace(x2psychroot, psychroot, model = "ER", type = "discrete", marginal = TRUE)
fitER2_psychroot

    Ancestral Character Estimation

Call: ace(x = x2psychroot, phy = psychroot, type = "discrete", model = "ER", 
    marginal = TRUE)

    Log-likelihood: -126.5058 

Rate index matrix:
            warm host other host food marine terrestrial
warm host           .          1    1      1           1
other host          1          .    1      1           1
food                1          1    .      1           1
marine              1          1    1      .           1
terrestrial         1          1    1      1           .

Parameter estimates:
 rate index estimate std-err
          1  14.7976  3.0498

Scaled likelihoods at the root (type '...$lik.anc' to get them for all nodes):
  warm host  other host        food      marine terrestrial 
        0.2         0.2         0.2         0.2         0.2 
plotTree(psychroot,fsize=0.8,ftype="i")
nodelabels(node=1:psychroot$Nnode+Ntip(psychroot),pie=fitER2_psychroot$lik.anc,piecol = x2col,cex=0.5)
#tiplabels(pie=to.matrix(x2psychroot[psychroot$tip.label],levels(x1psychroot)),piecol = x2col,cex=0.3)
#add.simmap.legend(leg=sort(unique(x2psychroot)),colors=x2col,x=0.9*par()$usr[1],
#                  y=-max(nodeHeights(psychroot)),fsize=0.8)
#plotTree(M.tree,fsize=0.8,ftype="i")
tiplabels(pie=to.matrix(x2psychroot,sort(unique(x2psychroot))),piecol=x2col,cex=0.3)
add.simmap.legend(colors=x2col,prompt=FALSE,x=0.9*par()$usr[1],
                  y=-max(nodeHeights(psychroot)),fsize=0.8)

Predicted cold-adapted protein traits.

Figure 3.6

psych_genecluster_summ = as.data.frame(table(psych_PCAT$geneCluster))
colnames(psych_genecluster_summ) = c("geneCluster", "frequency")
highpcatfreq = as.data.frame(table(psych_highPCAT$geneCluster))
colnames(highpcatfreq) = c("geneCluster", "freq_highPCAT")
psych_genecluster_summ = left_join(psych_genecluster_summ, highpcatfreq)
Joining, by = "geneCluster"
psych_genecluster_summ$freq_highPCAT[is.na(psych_genecluster_summ$freq_highPCAT) == TRUE] <- 0
psych_genecluster_summ$perc_highPCAT = psych_genecluster_summ$freq_highPCAT/psych_genecluster_summ$frequency
psych_genecluster_summ_nosingletons = psych_genecluster_summ %>% filter(frequency != 1)
(perHPCAT = ggplot(data = psych_genecluster_summ, aes(x = perc_highPCAT)) + geom_histogram() + theme_classic() + xlab("Percentage of CDS in geneCluster that are classified as 'highly cold adaptive'"))

(perHPCAT_noS = ggplot(data = psych_genecluster_summ_nosingletons, aes(x = perc_highPCAT)) + geom_histogram() + theme_classic() + xlab("Percentage of CDS in geneCluster that are classified as 'highly cold adaptive', singletons removed"))

ggarrange(perHPCAT, perHPCAT_noS, align = 'h', labels = c("A", "B"))
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Figure 3.7

psych_PCAT_strainID_summ = as.data.frame(table(psych_PCAT$strainID))
colnames(psych_PCAT_strainID_summ) = c("strainID", "frequency")
highpcat_bystrain = as.data.frame(table(psych_highPCAT$strainID))
colnames(highpcat_bystrain) = c("strainID", "freq_highPCAT")
psych_PCAT_strainID_summ = left_join(psych_PCAT_strainID_summ, highpcat_bystrain)
Joining, by = "strainID"
psych_PCAT_strainID_summ$perc_highPCAT = psych_PCAT_strainID_summ$freq_highPCAT/psych_PCAT_strainID_summ$frequency
perc_highPCAT = psych_PCAT_strainID_summ$perc_highPCAT
names(perc_highPCAT) = psych_PCAT_strainID_summ$strainID
setdiff(names(perc_highPCAT), P.tree.noout$tip.label)
[1] "P_sp_IAM12030_72-O-c"
phylo_PCAT = phylosig(tree = P.tree.noout, x = perc_highPCAT, test = TRUE)
[1] "some species in x are missing from tree, dropping missing taxa from x"
[1] "some species in tree are missing from x , dropping missing taxa from the tree"
phylo_PCAT

Phylogenetic signal K : 0.456351 
P-value (based on 1000 randomizations) : 0.001 
(HPCAT_bystrain = ggplot(data = psych_PCAT_strainID_summ, aes(x = perc_highPCAT)) + geom_histogram() + theme_classic() + xlab("Percentage of highly cold adaptive proteins by strain"))

psych_genome_summaries = left_join(psych_genome_summaries, psych_strain_collection[,c(3,5,21,27)])
Joining, by = "strain_plus_code"
psych_PCAT_strainID_summ$strainID = as.character(psych_PCAT_strainID_summ$strainID)
psych_PCAT_strainID_summ$strainID[psych_PCAT_strainID_summ$strainID == "P_sp_IAM12030_72-O-c"] <- "P_sp_IAM12030-72-O-c"
psych_PCAT_strainID_summ = left_join(psych_PCAT_strainID_summ, psych_genome_summaries[,c(19,5,20,21)])
Joining, by = "strainID"
psych_PCAT_strainID_summ$temprange = "mesophile"
psych_PCAT_strainID_summ$temprange[psych_PCAT_strainID_summ$strainID == "P_frigidicola_ACAM304" |
                                     psych_PCAT_strainID_summ$strainID == "P_frigidicola_ACAM309" |
                                     psych_PCAT_strainID_summ$strainID == "P_sp_72-O-c" |
                                     psych_PCAT_strainID_summ$strainID == "P_sp_IAM12030-72-O-c" |
                                     psych_PCAT_strainID_summ$strainID == "P_urativorans_ACAM311"] <- "psychrophile"
wilcox.test(perc_highPCAT ~ temprange, data = psych_PCAT_strainID_summ)

    Wilcoxon rank sum test with continuity correction

data:  perc_highPCAT by temprange
W = 256, p-value = 0.2999
alternative hypothesis: true location shift is not equal to 0
kruskal.test(frequency ~ ISME_source, data = psych_PCAT_strainID_summ)

    Kruskal-Wallis rank sum test

data:  frequency by ISME_source
Kruskal-Wallis chi-squared = 16.388, df = 4, p-value = 0.00254
kruskal.test(Genome.size..bp. ~ ISME_source, data = psych_PCAT_strainID_summ)

    Kruskal-Wallis rank sum test

data:  Genome.size..bp. by ISME_source
Kruskal-Wallis chi-squared = 14.093, df = 4, p-value = 0.007005
(genes_by_isosource = ggplot(data = psych_PCAT_strainID_summ, aes(x = ISME_source, y = frequency)) + 
  geom_boxplot(alpha = 0, aes(color = ISME_source)) + 
    geom_point(aes(color = ISME_source)) +
    scale_color_manual(values = ISMEcolors) +
    geom_signif(comparisons = list(c("warm host", "other host"), c("warm host", "food"), c("other host", "marine"), c("other host", "terrestrial"), c("food", "marine"), c("food", "terrestrial")), map_signif_level = T) +
  theme_classic() +
    ylab("# of genes per genome"))

#all pairwise comparisons:
#comparisons = split(t(combn(levels(psych_PCAT_strainID_summ$ISME_source), 2)), seq(nrow(t(combn(levels(psych_PCAT_strainID_summ$ISME_source), 2)))))
pairwise.wilcox.test(x = psych_PCAT_strainID_summ$Genome.size..bp., g = psych_PCAT_strainID_summ$ISME_source, p.adjust.method = 'BH')

    Pairwise comparisons using Wilcoxon rank sum test 

data:  psych_PCAT_strainID_summ$Genome.size..bp. and psych_PCAT_strainID_summ$ISME_source 

            food  marine other host terrestrial
marine      0.093 -      -          -          
other host  0.951 0.046  -          -          
terrestrial 0.031 0.951  0.031      -          
warm host   0.031 0.951  0.031      0.951      

P value adjustment method: BH 
pairwise.wilcox.test(x = psych_PCAT_strainID_summ$frequency, g = psych_PCAT_strainID_summ$ISME_source, p.adjust.method = 'BH')
cannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with tiescannot compute exact p-value with ties

    Pairwise comparisons using Wilcoxon rank sum test 

data:  psych_PCAT_strainID_summ$frequency and psych_PCAT_strainID_summ$ISME_source 

            food  marine other host terrestrial
marine      0.046 -      -          -          
other host  1.000 0.032  -          -          
terrestrial 0.034 0.913  0.032      -          
warm host   0.021 0.655  0.021      0.913      

P value adjustment method: BH 
(HCA_by_temprange = ggplot(data = psych_PCAT_strainID_summ, aes(x = temprange, y = perc_highPCAT)) + 
    geom_boxplot(alpha = 0) +
    theme_classic() +
    ylab("% of genes that are highly cold adapted"))

psych_PCAT_strainID_summ$ISME_source = factor(psych_PCAT_strainID_summ$ISME_source, levels = c("warm host", "other host", "food", "marine", "terrestrial"))
(HCA_by_isosource = ggplot(data = psych_PCAT_strainID_summ, aes(x = ISME_source, y = perc_highPCAT)) + 
  geom_boxplot(alpha = 0, aes(color = ISME_source)) + 
    geom_point(aes(color = ISME_source)) +
    scale_color_manual(values = ISMEcolors) +
  theme_classic() +
    ylab("% of genes that are highly cold adapted"))

kruskal.test(perc_highPCAT ~ ISME_source, data = psych_PCAT_strainID_summ)

    Kruskal-Wallis rank sum test

data:  perc_highPCAT by ISME_source
Kruskal-Wallis chi-squared = 8.5337, df = 4, p-value = 0.07387
ggarrange(HCA_by_temprange, HCA_by_isosource, labels = c("A", "B"), widths = c(1, 3))

figure 3.8

highPCATlocus = psych_highPCAT %>% select(locus_tag) %>% unlist() %>% unname()
psych_PCAT$PCAT = NA
psych_PCAT$PCAT[psych_PCAT$locus_tag %in% highPCATlocus] <- "high"
psych_PCAT$PCAT[is.na(psych_PCAT$PCAT) == TRUE] <- "not"
psych_PCAT$PCAT = factor(psych_PCAT$PCAT, levels = c("not", "high"))
psych_PCAT_annot = left_join(psych_PCAT, multiCOG_genes_corrected)
Joining, by = "geneCluster"
(function_PCAT = ggplot(data = psych_PCAT_annot, 
                          aes(x = PCAT, fill = COG_category)) + 
    geom_bar(stat = 'count', position = 'fill') + 
    scale_fill_manual(values = COGcols) +
    theme_classic())

COG_PCAT_chi = chisq.test(t(table(psych_PCAT_annot$PCAT, psych_PCAT_annot$COG_category)))
COG_PCAT_chi

    Pearson's Chi-squared test

data:  t(table(psych_PCAT_annot$PCAT, psych_PCAT_annot$COG_category))
X-squared = 3750.4, df = 23, p-value < 2.2e-16
COG_PCAT_cor = corrplot(COG_PCAT_chi$residuals, is.cor = FALSE)

#arrange function_PCAT w corrplot in illustrator
LS0tCnRpdGxlOiAiVGhlc2lzIENoYXB0ZXIgMyBBbmFseXNpcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKQ2hhcHRlciAzIEFic3RyYWN0OiAKRWNvbG9naWNhbCBuaWNoZSBjYW4gZHJpdmUgdGhlIGdlbm9taWMgZGl2ZXJzaWZpY2F0aW9uIG9mIGNsb3NlbHkgcmVsYXRlZCBiYWN0ZXJpYWwgc3BlY2llcy4gSGVyZSwgSSBhcHBseSBnZW5vbWljIGFuYWx5c2VzIHRvIHRoZSBnZW51cyAgUHN5Y2hyb2JhY3RlciwgIGtub3duIGZvciBpdHMgcGFydGljdWxhcmx5IHdpZGUgZWNvbG9naWNhbCBkaXN0cmlidXRpb24uIEkgcGVyZm9ybWVkIGEgcGFuLWdlbm9tZSBhbmFseXNpcywgbWljcm9iaWFsIHBhbi1nZW5vbWUgd2lkZSBhc3NvY2lhdGlvbiwgYW5jZXN0cmFsIGNoYXJhY3RlciBlc3RpbWF0aW9ucywgYW5kIGFuYWx5c2lzIG9mIHNlbGVjdGlvbiBvbiBwcm90ZWluIHNlcXVlbmNlcyBvZiA4NSBzdHJhaW5zIG9mICBQc3ljaHJvYmFjdGVyICB0byBjbGFyaWZ5IHRoZSBpbnRlcmFjdGlvbnMgYmV0d2VlbiBpc29sYXRpb24gc291cmNlIGFuZCBQc3ljaHJvYmFjdGVyICBnZW5vbWUgZXZvbHV0aW9uLiBUaGVyZSBpcyBzb21lIGV2aWRlbmNlIHRoYXQgUHN5Y2hyb2JhY3RlciBpc29sYXRpb24gc291cmNlIGNvcnJlbGF0ZXMgd2l0aCBhdmFpbGFibGUgZ2VuZSBwb29sOyBlYWNoIGlzb2xhdGlvbiBzb3VyY2UgLSBmcm9tIHdhcm0tYm9kaWVkIGhvc3RzIHN1Y2ggYXMgbWFtbWFscyBvciBiaXJkcywgb3RoZXIgaG9zdHMgbGlrZSBmaXNoIG9yIGludmVydGVicmF0ZXMsIHRvIGZvb2QgcHJvY2Vzc2luZywgbWFyaW5lLCBvciB0ZXJyZXN0cmlhbCBlbnZpcm9ubWVudHMgLSBpcyBjb3JyZWxhdGVkIHdpdGggdW5pcXVlIGdlbmVzIGZyb20gZGlmZmVyZW50IENPRyBjYXRlZ29yaWVzLiBTdHJhaW5zIGlzb2xhdGVkIGZyb20gaW52ZXJ0ZWJyYXRlIGFuZCBmaXNoIGhvc3RzLCBhcyB3ZWxsIGFzIGZvb2QgcHJvY2Vzc2luZyBlbnZpcm9ubWVudHMsIGhhdmUgaGlnaGVyIG51bWJlcnMgb2YgdG90YWwgZ2VuZXMsIHRob3VnaCBmZXdlciB1bmlxdWUgZ2VuZXMgdGhhbiBzdHJhaW5zIGZyb20gbWFtbWFscywgYmlyZHMsIG9yIG1hcmluZSBlbnZpcm9ubWVudHMuIEFmdGVyIGFjY291bnRpbmcgZm9yIHBvcHVsYXRpb24gc3RydWN0dXJlLCBob3dldmVyLCB2ZXJ5IGZldyBnZW5lcyBjb3JyZWxhdGUgd2l0aCBpc29sYXRpb24gc291cmNlOyB0aGVyZSBpcyBzb21lIGV2aWRlbmNlIGZvciBpbmNyZWFzZWQgaG9yaXpvbnRhbCBnZW5lIHRyYW5zZmVyIGluIHN0cmFpbnMgaXNvbGF0ZWQgZnJvbSBmaXNoIGFuZCBpbnZlcnRlYnJhdGVzLCBhbmQgZXZpZGVuY2UgZm9yIGluY3JlYXNlZCBiaW9maWxtIGZvcm1hdGlvbiBpbiBzdHJhaW5zIGlzb2xhdGVkIGZyb20gZm9vZC1wcm9jZXNzaW5nIGVudmlyb25tZW50cy4gQW5jZXN0cmFsIGNoYXJhY3RlciBlc3RpbWF0aW9uIHN1cHBvcnRzIHRoYXQgIFBzeWNocm9iYWN0ZXIgIGFyZSBkZXNjZW5kZWQgZnJvbSBhIHdhcm0gaG9zdC1hc3NvY2lhdGVkIGJhY3Rlcml1bS4gRmluYWxseSwgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiBpc29sYXRpb24gc291cmNlIGFuZCBjb2xkLWFkYXB0YXRpb24gb2YgcHJvdGVpbnMuIE92ZXJhbGwsIG15IHJlc3VsdHMgc2hvdyB0aGF0IGlzb2xhdGlvbiBzb3VyY2UgaGFzIHNvbWUgaW1wYWN0IG9uICBQc3ljaHJvYmFjdGVyIGdlbm9tZSBldm9sdXRpb24sIHRob3VnaCB0aGUgcG9wdWxhdGlvbiBzdHJ1Y3R1cmUgb2YgdGhlIGdlbnVzIG1ha2VzIGl0IGRpZmZpY3VsdCB0byBkaXNlbnRhbmdsZSBpdHMgZWZmZWN0cy4KCgpgYGB7ciBzZXR1cCwgZWNobz1GQUxTRX0Kc2V0d2QoIn4vb3duQ2xvdWQvUHN5Y2hyb2JhY3Rlci9EYXRhX0FuYWx5c2lzL1BBTlgvdGhlc2lzLyIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShnZ3NpZ25pZikKCmxpYnJhcnkoc2VxaW5yKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHBoeXRvb2xzKQoKbGlicmFyeShtaWNyb3BhbikKbGlicmFyeShjb3JycGxvdCkKCmxpYnJhcnkodHJlZVdBUykKCnBzeWNoX1BDQVQgPSByZWFkLmRlbGltKCJQc3ljaF8yMDIwMTAxNl9QQ0FULnR4dCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQp1bmlyZWZfdlBzeWNocm9iYWN0ZXJfYmxhc3QgPC0gcmVhZC5kZWxpbSgiUHN5Y2hfMjAyMDEwMTZfdnNfdW5pcmVmX0NVU1RPTUJMQVNUb3V0cHV0LnR4dCIsIGhlYWRlciA9IFQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQoKUC50cmVlID0gcmVhZC50cmVlKCJQc3ljaGZpbmFsX291dGdyb3VwTW9yYXhsaW5jb2xuaWkubndrIikKUC50cmVlID0gcm9vdChQLnRyZWUsICJNb3JheGVsbGFfbGluY29sbmlpIiwgcmVzb2x2ZS5yb290ID0gVCkKUC50cmVlLm5vb3V0ID0gZHJvcC50aXAoUC50cmVlLCAiTW9yYXhlbGxhX2xpbmNvbG5paSIpClAudHJlZS5ub291dCRlZGdlLmxlbmd0aFtQLnRyZWUubm9vdXQkZWRnZS5sZW5ndGggPT0gMF0gPC0gMC4wMDAwMDAwMDEKCnBzeWNoX2dlbm9tZV9zdW1tYXJpZXMgPSByZWFkLmRlbGltKCJnZW5vbWVfc3VtbWFyeV9zdGF0aXN0aWNzLnR4dCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQpwc3ljaF9zdHJhaW5fY29sbGVjdGlvbiA9IHJlYWQuZGVsaW0oIlBzeWNocm9iYWN0ZXJfc3RyYWluaW5mb19tYXN0ZXJ0YWJsZS50eHQiLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKCnBzeWNoX2VnZ25vZ19hbm5vdGF0aW9ucyA9IHJlYWQuZGVsaW0oIlBzeWNoXzIwMjAxMDE2X2VnZ25vZ19jbHVzdGVyc19hbm5vdGF0aW9ucy50eHQiLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKCnBzeWNoX2dwYSA9IHJlYWQuZGVsaW0oInBzeWNoXzIwMjAxMDE2X25vZGFzaF9ncGEudHh0Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpCgpJU01FY29sb3JzID0gYygiI0Y5RDUwMyIsICIjNURDODYzIiwgIiMyMTkwOEMiLCAiIzNCNTI4QiIsICIjNDQwMTU0IikKCgojb3V0cHV0IAp1bmlyZWZfUENBVCA9IHJlYWQuZGVsaW0oInBzeWNoMjAyMDEwMTZfdW5pcmVmUENBVC50eHQiLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKcHN5Y2hfaGlnaFBDQVQgPSByZWFkLmRlbGltKCJwc3ljaF9oaWdoUENBVC50eHQiLCBzdHJpbmdzQXNGYWN0b3JzID0gRikgI3N0cmFpbiBuYW1lcyBpbiB0aGUgUkRTIGZpbGUgaGF2ZSB0aGUgZnVua3kgZGFzaGVzIGlzc3VlCnBzeWNoX21lZGxvUENBVCA9IHJlYWRSRFMoIlBzeWNocm9iYWN0ZXJfbm90aGlnaFBDQVRfZ2VuZXByb2R1Y3RzLlJEUyIpCmdlbmVzX21hdF9mb3JwYW4gPSByZWFkLmRlbGltKCJnZW5lbWF0cml4X251bUdDcGVyaXNvbGF0ZS50eHQiLCBzdHJpbmdzQXNGYWN0b3JzID0gRiwgcm93Lm5hbWVzID0gMSkKbXVsdGljb2dfZ2VuZWNsdXN0ZXJzID0gcmVhZC5kZWxpbSgiZ2VuZWNsdXN0ZXJfQ09HX2NhdGVnb3JpZXMudHh0Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpCgpzdHJhaW5fY29sbGVjdGlvbiA9IHJlYWQuZGVsaW0oIlBzeWNocm9iYWN0ZXJQTFVTX3N0cmFpbmluZm9fbWFzdGVydGFibGUudHh0Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpCgpNLnRyZWUgPSByZWFkLnRyZWUoIlBzeWNocm9iYWN0ZXJNb3JheGVsbGFwaHlsb2dlbnlfQXB1eWFuZ2Vuc2lzb3V0Z3JvdXAubndrIikKTS50cmVlID0gcm9vdChNLnRyZWUsICJBX3B1eWFuZ2Vuc2lzIiwgcmVzb2x2ZS5yb290ID0gVCkKTS50cmVlJGVkZ2UubGVuZ3RoW00udHJlZSRlZGdlLmxlbmd0aCA9PSAwXSA8LSAwLjAwMDAwMDAwMQoKSVNNRWNvbG9ycyA9IGMoIiNGOUQ1MDMiLCAiIzVEQzg2MyIsICIjMjE5MDhDIiwgIiMzQjUyOEIiLCAiIzQ0MDE1NCIpCgpnZW5lbWF0cml4X3RyZWV3YXMgPSByZWFkLmRlbGltKCJnZW5lbWF0cml4X2Zvcl90cmVld2FzX2ZpeGVkZGFzaGVzLnR4dCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGLCByb3cubmFtZXMgPSAxKQoKYGBgCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAKCiAKIAojUGFuLWdlbm9tZSBzdW1tYXJ5CmBgYHtyfQpnZW5lbWF0cml4ID0gcHN5Y2hfZ3BhWywxMDpuY29sKHBzeWNoX2dwYSldICNvciB3aGljaGV2ZXIgY29sdW1uIHlvdXIgaXNvbGF0ZSBkYXRhIHN0YXJ0cyBhdApyb3duYW1lcyhnZW5lbWF0cml4KSA9IHBzeWNoX2dwYSRnZW5lQ2x1c3RlcgpnZW5lbWF0cml4ID0gYXBwbHkoZ2VuZW1hdHJpeCwgIDIsICBmdW5jdGlvbih4KSBnc3ViKCJeJHxeICQiLCAgTkEsICB4KSkgI3JlcGxhY2UgZW1wdHkgY2VsbHMgd2l0aCBOQQoKdHJhbnNmb3JtX2Z1bmMgPSBmdW5jdGlvbih4KSB7IGlmIChpcy5uYSh4KSA+IDApIHsgciA9IDAgfSBlbHNlIHsgciA9IDEgfSB9ICNjcmVhdGVzIGEgZnVuY3Rpb24gdG8gcmVjb2duaXplIHdoZW4gYSBjZWxsIGhhcyBpbmZvcm1hdGlvbiBpbiBpdCAoaW4gdGhpcyBjYXNlLCAgd2hlbiBhbiBpc29sYXRlIEhBUyBhIGdlbmUpIGFuZCByZXBsYWNlIHRoYXQgY2VsbCdzIGNvbnRlbnRzIHdpdGggIjEiLiBvdGhlcndpc2UsICByZXBsYWNlIHRoYXQgY2VsbCdzIGNvbnRlbnRzIHdpdGggIjAiCmdlbmVtYXRyaXhfYmluYXJ5IDwtIGFwcGx5KGdlbmVtYXRyaXgsIDIsIGZ1bmN0aW9uKHgpe3NhcHBseSh4LCAgdHJhbnNmb3JtX2Z1bmMpfSkgI2xvb3AgdGhlIGZ1bmN0aW9uIGNyZWF0ZWQgaW4gdGhlIHN0ZXAgYWJvdmUgdGhyb3VnaCBvdXIgdHJhbnNwb3NlZCBnZW5lIG1hdHJpeAoKZ2VuZW1hdHJpeF9iaW5hcnlfdCA9IHQoZ2VuZW1hdHJpeF9iaW5hcnkpICN0cmFuc3Bvc2UgdGhlIG1hdHJpeDsgbmVlZCBzdHJhaW5zIHRvIGJlIG9uIHRoZSByb3dzIGFuZCBnZW5lcyB0byBiZSBvbiB0aGUgY29sdW1ucwpnZW5lbWF0cml4X2JpbmFyeV90ID0gYXMuZGF0YS5mcmFtZShnZW5lbWF0cml4X2JpbmFyeV90KQpnZW5lbWF0cml4X2JpbmFyeV90ID0gZ2VuZW1hdHJpeF9iaW5hcnlfdCAlPiUKICBtdXRhdGVfaWYoaXMuZmFjdG9yLCBhcy5udW1lcmljKSAjdCgpIHdpbGwgdHJhbnNmb3JtIHlvdXIgZGF0YSBpbnRvIHRoZSAibWF0cml4IiBmb3JtYXQsIGFuZCB0cmVld2FzIHdhbnRzIGl0IGluIGEgZGF0YWZyYW1lIGZvcm1hdCwgc28gdGhpcyB0cmFuc2Zvcm1zIGl0IGJhY2sKcm93bmFtZXMoZ2VuZW1hdHJpeF9iaW5hcnlfdCkgPSBjb2xuYW1lcyhnZW5lbWF0cml4X2JpbmFyeSkKI3RvIHByb2R1Y2Ugb3V0cHV0IGZpbGUgImdlbmVtYXRyaXhfZm9yX3RyZWV3YXNfZml4ZWRkYXNoZXMudHh0IgoKCmdlbmVzX21hdCA9IGdlbmVtYXRyaXggCmdlbmVzX21hdF9udW1iZXJlZCA9IGdlbmVzX21hdApmb3IoaSBpbiAxOm5yb3coZ2VuZXNfbWF0KSkgewogIGZvciAoaiBpbiAxOm5jb2woZ2VuZXNfbWF0KSkgewogICAgY2VsbCA9IGdlbmVzX21hdFtpLGpdCiAgICBudW0gPSBzdHJfY291bnQoY2VsbCwgIiwiKSArIDEKICAgIGlmIChpcy5uYShjZWxsKSA9PSBUUlVFKSB7bnVtID0gMH0KICAgIGdlbmVzX21hdF9udW1iZXJlZFtpLGpdID0gbnVtCiAgfQp9CnJvd25hbWVzKGdlbmVzX21hdF9udW1iZXJlZCkgPSBwc3ljaF9ncGEkZ2VuZUNsdXN0ZXIKZ2VuZXNfbWF0X251bWJlcmVkID0gYXMuZGF0YS5mcmFtZShnZW5lc19tYXRfbnVtYmVyZWQpCmdlbmVzX21hdF9udW1iZXJlZCA9IGdlbmVzX21hdF9udW1iZXJlZCAlPiUKICBtdXRhdGVfYWxsKGFzLmNoYXJhY3RlcikgJT4lCiAgbXV0YXRlX2FsbChhcy5udW1lcmljKQoKbGlicmFyeShtaWNyb3BhbikKZ2VuZXNfbWF0X2ZvcnBhbiA9IHQoZ2VuZXNfbWF0X251bWJlcmVkKQpjb2xuYW1lcyhnZW5lc19tYXRfZm9ycGFuKSA9IHJvd25hbWVzKGdlbmVzX21hdCkKcmFyZSA9IHJhcmVmYWN0aW9uKHBhbi5tYXRyaXggPSBnZW5lc19tYXRfZm9ycGFuLCBuLnBlcm0gPSA5OTkpCnJhcmUubWVsdCA9IHJlc2hhcGUyOjptZWx0KHJhcmUsIGlkID0gYygiR2Vub21lIikpCgoocGFucmFyZWZhY3Rpb24gPSBnZ3Bsb3QoZGF0YSA9IHJhcmUubWVsdCwgYWVzKHggPSBHZW5vbWUsIHkgPSB2YWx1ZSkpICsgCiAgICBnZW9tX2JveHBsb3QoYWVzKHggPSBHZW5vbWUsIGdyb3VwID0gR2Vub21lKSwgb3V0bGllci5zaGFwZSA9IE5BKSArIAogICAgdGhlbWVfY2xhc3NpYygpICsgCiAgICB4bGFiKCJOdW1iZXIgb2YgR2Vub21lcyIpICsgeWxhYigiTnVtYmVyIG9mIE5vdmVsIE9ydGhvbG9ncyIpKQoKaGVhcHMocGFuLm1hdHJpeCA9IGdlbmVzX21hdF9mb3JwYW4sIG4ucGVybSA9IDk5OSkKCndhcm0gPSBwc3ljaF9zdHJhaW5fY29sbGVjdGlvbiAlPiUgZmlsdGVyKElTTUVfc291cmNlID09ICJ3YXJtIGhvc3QiKSAlPiUgc2VsZWN0KHN0cmFpbklEKSAlPiUgdW5saXN0KCkgJT4lIHVubmFtZSgpCm90aGVyID0gcHN5Y2hfc3RyYWluX2NvbGxlY3Rpb24gJT4lIGZpbHRlcihJU01FX3NvdXJjZSA9PSAib3RoZXIgaG9zdCIpICU+JSBzZWxlY3Qoc3RyYWluSUQpICU+JSB1bmxpc3QoKSAlPiUgdW5uYW1lKCkKZm9vZCA9IHBzeWNoX3N0cmFpbl9jb2xsZWN0aW9uICU+JSBmaWx0ZXIoSVNNRV9zb3VyY2UgPT0gImZvb2QiKSAlPiUgc2VsZWN0KHN0cmFpbklEKSAlPiUgdW5saXN0KCkgJT4lIHVubmFtZSgpCm1hcmluZSA9IHBzeWNoX3N0cmFpbl9jb2xsZWN0aW9uICU+JSBmaWx0ZXIoSVNNRV9zb3VyY2UgPT0gIm1hcmluZSIpICU+JSBzZWxlY3Qoc3RyYWluSUQpICU+JSB1bmxpc3QoKSAlPiUgdW5uYW1lKCkKdGVycmVzdHJpYWwgPSBwc3ljaF9zdHJhaW5fY29sbGVjdGlvbiAlPiUgZmlsdGVyKElTTUVfc291cmNlID09ICJ0ZXJyZXN0cmlhbCIpICU+JSBzZWxlY3Qoc3RyYWluSUQpICU+JSB1bmxpc3QoKSAlPiUgdW5uYW1lKCkKCmFsbHNlcXN1bSA9IHJvd1N1bXMoZ2VuZXNfbWF0X251bWJlcmVkKQpuYW1lcyhhbGxzZXFzdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQphbGxpc29zdW0gPSByb3dTdW1zKGdlbmVtYXRyaXhfYmluYXJ5KQpuYW1lcyhhbGxpc29zdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQoKcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5ID0gcmJpbmQoYWxsc2Vxc3VtLCBhbGxpc29zdW0pCgpwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkgPSB0KHBhbmdlbm9tZV9ieV9pc29sYXRpb25fc3VtbWFyeSkKcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5ID0gYXMuZGF0YS5mcmFtZShwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkpCnBhbmdlbm9tZV9ieV9pc29sYXRpb25fc3VtbWFyeSRnZW5lQ2x1c3RlciA9IHJvd25hbWVzKHBhbmdlbm9tZV9ieV9pc29sYXRpb25fc3VtbWFyeSkKCgpwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkkb3ZlcmFsbF9wYW5fY2F0ID0gTkEKcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5JG92ZXJhbGxfcGFuX2NhdFtwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkkYWxsaXNvc3VtID49IDg0XSA8LSAiY29yZSIKcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5JG92ZXJhbGxfcGFuX2NhdFtwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkkYWxsaXNvc3VtIDw9IDgzICYgcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5JGFsbGlzb3N1bSA+PSA3N10gPC0gInNvZnQgY29yZSIKcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5JG92ZXJhbGxfcGFuX2NhdFtwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkkYWxsaXNvc3VtIDw9IDc2ICYgcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5JGFsbGlzb3N1bSA+PSAyIF0gPC0gInNoZWxsIgpwYW5nZW5vbWVfYnlfaXNvbGF0aW9uX3N1bW1hcnkkb3ZlcmFsbF9wYW5fY2F0W3Bhbmdlbm9tZV9ieV9pc29sYXRpb25fc3VtbWFyeSRhbGxpc29zdW0gPT0gMSBdIDwtICJjbG91ZCIKCnBhbmdlbm9tZV9ieV9pc29sYXRpb25fc3VtbWFyeSRvdmVyYWxsX3Bhbl9jYXQgPSBmYWN0b3IocGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5JG92ZXJhbGxfcGFuX2NhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29yZSIsICJzb2Z0IGNvcmUiLCAic2hlbGwiLCAiY2xvdWQiKSkKCmBgYAoKIyMjRmlndXJlIDMuMSBwYW4tZ2Vub21lIHJhcmVmYWN0aW9uIGFuZCBjYXRlZ29yaWVzCmBgYHtyfQoocGFuY2F0ZWdvcnlfY291bnQgPSBnZ3Bsb3QoZGF0YSA9IHBhbmdlbm9tZV9ieV9pc29sYXRpb25fc3VtbWFyeSwgYWVzKHggPSBvdmVyYWxsX3Bhbl9jYXQpKSArIAogICAgZ2VvbV9iYXIoc3RhdCA9ICdjb3VudCcpICsKICAgIHRoZW1lX2NsYXNzaWMoKQopCgpnZ2FycmFuZ2UocGFuY2F0ZWdvcnlfY291bnQsIHBhbnJhcmVmYWN0aW9uLCBhbGlnbiA9ICdoJywgd2lkdGhzID0gYygxLCAyKSkKCgpgYGAKIyMjRmlndXJlIDMuMiBmdW5jdGlvbmFsIGFuYWx5c2lzIG9mIGRpZmZlcmVudCBwYW4tZ2Vub21lIGNhdGVnb3JpZXMgCgpgYGB7cn0KQ09HX211bHRpX2NhdHMgPSBtdWx0aWNvZ19nZW5lY2x1c3RlcnMgJT4lIGZpbHRlcihDT0cyICE9ICIiKQojanVzdCByZWFsaXplZCB0aGF0IHRoaXMgZG9lcyBub3QgaGF2ZSBldmVyeSBDT0cgY2F0IGZvciBldmVyeSBzdHJhaW4sIGZvciBleGFtcGxlIHRoZXJlIGlzIG5vIENPRyBDQVQgIkIiIGZvciBmcmlnaWRpY29sYV8wNTYuLi4KI3dpbGwgaGF2ZSB0byBtYWtlIGEgbmV3IGRhdGEgZnJhbWUgdG8gcG9wdWxhdGUgZnJvbSBzY3JhdGNoCkNPR19tdWx0aV9jYXRzX3NlcGFyYXRlZCA9IGRhdGEuZnJhbWUoKQpmb3IoaSBpbiAxOm5yb3coQ09HX211bHRpX2NhdHMpKSB7CiAgZ2VuID0gQ09HX211bHRpX2NhdHNbaSwxXQogIGNhdCA9IENPR19tdWx0aV9jYXRzW2ksMl0KICBDT0cxID0gQ09HX211bHRpX2NhdHNbaSwzXQogIGR1bW15MSA9IGMoZ2VuLCBjYXQsIENPRzEpCiAgQ09HX211bHRpX2NhdHNfc2VwYXJhdGVkID0gcmJpbmQuZGF0YS5mcmFtZShDT0dfbXVsdGlfY2F0c19zZXBhcmF0ZWQsIGFzLmNoYXJhY3RlcihkdW1teTEpLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKICBDT0cyID0gQ09HX211bHRpX2NhdHNbaSw0XQogIGR1bW15MiA9IGMoZ2VuLCBjYXQsIENPRzIpCiAgQ09HX211bHRpX2NhdHNfc2VwYXJhdGVkID0gcmJpbmQuZGF0YS5mcmFtZShDT0dfbXVsdGlfY2F0c19zZXBhcmF0ZWQsIGFzLmNoYXJhY3RlcihkdW1teTIpLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKICBDT0czID0gQ09HX211bHRpX2NhdHNbaSw1XQogIGlmIChDT0czICE9ICIiKXsKICAgIGR1bW15MyA9IGMoZ2VuLCBjYXQsIENPRzMpCiAgICBDT0dfbXVsdGlfY2F0c19zZXBhcmF0ZWQgPSByYmluZC5kYXRhLmZyYW1lKENPR19tdWx0aV9jYXRzX3NlcGFyYXRlZCwgYXMuY2hhcmFjdGVyKGR1bW15MyksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQogIH0KICBDT0c0ID0gQ09HX211bHRpX2NhdHNbaSw2XQogIGlmIChDT0c0ICE9ICIiKXsKICAgIGR1bW15NCA9IGMoZ2VuLCBjYXQsIENPRzQpCiAgICBDT0dfbXVsdGlfY2F0c19zZXBhcmF0ZWQgPSByYmluZC5kYXRhLmZyYW1lKENPR19tdWx0aV9jYXRzX3NlcGFyYXRlZCwgYXMuY2hhcmFjdGVyKGR1bW15NCksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQogIH0KfQpjb2xuYW1lcyhDT0dfbXVsdGlfY2F0c19zZXBhcmF0ZWQpID0gYygiZ2VuZUNsdXN0ZXIiLCAicGFuX2NhdGVnb3J5IiwgIkNPR19jYXRlZ29yeSIpCgpDT0dfc2luZ2xlX2NhdHMgPSBtdWx0aWNvZ19nZW5lY2x1c3RlcnMgJT4lIGZpbHRlcihDT0cyID09ICIiKSAlPiUKICBzZWxlY3QoZ2VuZUNsdXN0ZXIsIHBhbl9jYXRlZ29yeSwgQ09HMSkKY29sbmFtZXMoQ09HX3NpbmdsZV9jYXRzKVszXSA9ICJDT0dfY2F0ZWdvcnkiCgptdWx0aUNPR19nZW5lc19jb3JyZWN0ZWQgPSByYmluZChDT0dfbXVsdGlfY2F0c19zZXBhcmF0ZWQsIENPR19zaW5nbGVfY2F0cykKCm11bHRpQ09HX2dlbmVzX2NvcnJlY3RlZCRwYW5fY2F0ZWdvcnkgPSBmYWN0b3IobXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkJHBhbl9jYXRlZ29yeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29yZSIsICJzb2Z0Y29yZSIsICJzaGVsbCIsICJjbG91ZCIpKQoKbXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkJENPR19jYXRlZ29yeSA9IAogIGZhY3RvcihtdWx0aUNPR19nZW5lc19jb3JyZWN0ZWQkQ09HX2NhdGVnb3J5LCBsZXZlbHMgPSBjKCJEIiwgIk0iLCAiTiIsICJPIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBIiwgIkIiLCJKIiwgIksiLCAiTCIsIkMiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIlAiLCAiUSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTIiwgIlgiKSkKCgpDT0djb2xzID0gYygiIzcyMzAwQyIsICIjOTMwNzREIiwgIiNENjBENjkiLCAiI0VENUZBNiIsICIjQ0UxQjEzIiwgIiNBNTA1MDUiLCAiI0U1NTMwQSIsICIjRTI3NzBDIiwgIiNGOUExMzgiLCAKICAgICAgICAgIiNGN0YwNzIiLCAiI0Y3RDIzOSIsICIjQ0NGNDNCIiwgIiM1QkI3M0QiLCAiIzA1N0YyOCIsIAogICAgICAgICAiIzA1NTQxQSIsICIjMjA5OThCIiwgIiM2MEIxRjQiLCAiIzE0NThGMiIsICIjNTE0MUFGIiwgIiMxRjA0OEUiLCAiIzMxMDg3MiIsICIjNTIwNzc1IiwgCiAgICAgICAgICIjOUY5RkEwIiwgIiMzOTM4M0EiKQoKKGZ1bmN0aW9uX3BhbmNhdCA9IGdncGxvdChkYXRhID0gbXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHBhbl9jYXRlZ29yeSwgZmlsbCA9IENPR19jYXRlZ29yeSkpICsgCiAgICBnZW9tX2JhcihzdGF0ID0gJ2NvdW50JywgcG9zaXRpb24gPSAnZmlsbCcpICsgCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBDT0djb2xzKSArCiAgICB0aGVtZV9jbGFzc2ljKCkpCgoKQ09HX3BhbmNhdF9jaGkgPSBjaGlzcS50ZXN0KHQodGFibGUobXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkJHBhbl9jYXRlZ29yeSwgbXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkJENPR19jYXRlZ29yeSkpKQpDT0dfcGFuY2F0X2NoaQpDT0dfcGFuY2F0X2NvciA9IGNvcnJwbG90KENPR19wYW5jYXRfY2hpJHJlc2lkdWFscywgaXMuY29yID0gRkFMU0UpCgojYWRkIGZ1bmN0aW9uX3BhbmNhdCBhbmQgQ09HX3BhbmNhdF9jb3IgdG9nZXRoZXIgaW4gSWxsdXN0cmF0b3IKCmBgYAoKCiMjI0ZpZ3VyZSAzLjMgYW5kIHN0YXRzIGNvbXBhcmlzb25zIC0gcHJvcG9ydGlvbiBvZiBnZW5vbWUgZGV2b3RlZCB0byBlYWNoIHBhbiBnZW5vbWUgY2F0ZWdvcnkKYGBge3J9CnBzeWNoX1BDQVQgPSBsZWZ0X2pvaW4ocHN5Y2hfUENBVCwgcGFuZ2Vub21lX2J5X2lzb2xhdGlvbl9zdW1tYXJ5WywzOjRdKQoKdGVzdCA9IGxlZnRfam9pbihwc3ljaF9QQ0FUWyxjKDI6NCwzMyldLCBwc3ljaF9zdHJhaW5fY29sbGVjdGlvblssYygzLDI3KV0pCgp0ZXN0MiA9IGFzLmRhdGEuZnJhbWUodGFibGUodGVzdCRzdHJhaW5JRCwgdGVzdCRvdmVyYWxsX3Bhbl9jYXQpKQpjb2xuYW1lcyh0ZXN0MikgPSBjKCJzdHJhaW5JRCIsICJwYW5fY2F0IiwgImZyZXF1ZW5jeSIpCnRlc3QyID0gbGVmdF9qb2luKHRlc3QyLCBwc3ljaF9zdHJhaW5fY29sbGVjdGlvblssYygzLDI3KV0pCgpudW1iZXJfZ2VuZXNfcGVyc3RyYWluID0gYXMuZGF0YS5mcmFtZSh0YWJsZShwc3ljaF9QQ0FUJHN0cmFpbklEKSkKY29sbmFtZXMobnVtYmVyX2dlbmVzX3BlcnN0cmFpbikgPSBjKCJzdHJhaW5JRCIsICJudW1fZ2VuZXMiKQp0ZXN0MiA9IGxlZnRfam9pbih0ZXN0MiwgbnVtYmVyX2dlbmVzX3BlcnN0cmFpbikKdGVzdDIkSVNNRV9zb3VyY2VbdGVzdDIkc3RyYWluSUQgPT0gIlBfc3BfSUFNMTIwMzBfNzItTy1jIl0gPC0gInRlcnJlc3RyaWFsIgoKCmFnZ19wYW5jYXRfYnlpc29fYnlnZW5vbWUgPSBhZ2dyZWdhdGUodGVzdDIkZnJlcXVlbmN5LCBieSA9IGxpc3QodGVzdDIkSVNNRV9zb3VyY2UsIHRlc3QyJHBhbl9jYXQpLCBGVU4gPSBtZWFuKQpjb2xuYW1lcyhhZ2dfcGFuY2F0X2J5aXNvX2J5Z2Vub21lKSA9IGMoImlzb2xhdGlvbl9zb3VyY2UiLCAicGFuX2NhdCIsICJhdmVyYWdlX2dlbmVjbHVzdGVyc19wZXJnZW5vbWUiKQphZ2dfcGFuY2F0X2J5aXNvX2J5Z2Vub21lJHBhbl9jYXQgPSBmYWN0b3IoYWdnX3BhbmNhdF9ieWlzb19ieWdlbm9tZSRwYW5fY2F0LCBsZXZlbHMgPSBjKCJjb3JlIiwgInNvZnQgY29yZSIsICJzaGVsbCIsICJjbG91ZCIpKQphZ2dfcGFuY2F0X2J5aXNvX2J5Z2Vub21lX3NwID0gc3ByZWFkKGFnZ19wYW5jYXRfYnlpc29fYnlnZW5vbWUsIGtleSA9IHBhbl9jYXQsIHZhbHVlID0gYXZlcmFnZV9nZW5lY2x1c3RlcnNfcGVyZ2Vub21lKQoKY2hpc3FfcGFuX2lzbyA9IGNoaXNxLnRlc3QoYWdnX3BhbmNhdF9ieWlzb19ieWdlbm9tZV9zcFsxOjUsMjo1XSkKY29ycnBsb3QoY2hpc3FfcGFuX2lzbyRyZXNpZHVhbHMsIGlzLmNvcnIgPSBGKQoKYWdncmVnYXRlKHRlc3QyJGZyZXF1ZW5jeSwgYnkgPSBsaXN0KHRlc3QyJHBhbl9jYXQpLCBGVU4gPSBtZWFuKQoKcGFuY2F0X2J5aXNvX2J5Z2Vub21lID0gYXMuZGF0YS5mcmFtZSh0YWJsZShwc3ljaF9QQ0FUJHN0cmFpbklELCBwc3ljaF9QQ0FUJG92ZXJhbGxfcGFuX2NhdCkpCmNvbG5hbWVzKHBhbmNhdF9ieWlzb19ieWdlbm9tZSkgPSBjKCJzdHJhaW5JRCIsICJwYW5fY2F0IiwgImZyZXF1ZW5jeSIpCnBhbmNhdF9ieWlzb19ieWdlbm9tZSA9IGxlZnRfam9pbihwYW5jYXRfYnlpc29fYnlnZW5vbWUsIHBzeWNoX3N0cmFpbl9jb2xsZWN0aW9uWyxjKDMsMjcpXSkKcGFuY2F0X2J5aXNvX2J5Z2Vub21lID0gbGVmdF9qb2luKHBhbmNhdF9ieWlzb19ieWdlbm9tZSwgbnVtYmVyX2dlbmVzX3BlcnN0cmFpbikKCiAgCnBhbmNhdF9ieWlzb19ieWdlbm9tZSRJU01FX3NvdXJjZSA9IGZhY3RvcihwYW5jYXRfYnlpc29fYnlnZW5vbWUkSVNNRV9zb3VyY2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygid2FybSBob3N0IiwgIm90aGVyIGhvc3QiLCAiZm9vZCIsICJtYXJpbmUiLCAidGVycmVzdHJpYWwiKSkKcGFuY2F0X2J5aXNvX2J5Z2Vub21lJHBhbl9jYXQgPSBmYWN0b3IocGFuY2F0X2J5aXNvX2J5Z2Vub21lJHBhbl9jYXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29yZSIsICJzb2Z0IGNvcmUiLCAic2hlbGwiLCAiY2xvdWQiKSkKCnBhbmNhdF9ieWlzb19ieWdlbm9tZSRJU01FX3NvdXJjZVtwYW5jYXRfYnlpc29fYnlnZW5vbWUkc3RyYWluSUQgPT0gIlBfc3BfSUFNMTIwMzBfNzItTy1jIl0gPC0gInRlcnJlc3RyaWFsIgoKCnBhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCA9IHNwcmVhZChwYW5jYXRfYnlpc29fYnlnZW5vbWUsIGtleSA9ICJwYW5fY2F0IiwgdmFsdWUgPSAiZnJlcXVlbmN5IikKcGFuY2F0X2J5aXNvX2J5Z2Vub21lX3NwJGNvcmVfcHJvcCA9IHBhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCRjb3JlL3BhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCRudW1fZ2VuZXMKcGFuY2F0X2J5aXNvX2J5Z2Vub21lX3NwJHNvZnRjb3JlX3Byb3AgPSBwYW5jYXRfYnlpc29fYnlnZW5vbWVfc3AkYHNvZnQgY29yZWAvcGFuY2F0X2J5aXNvX2J5Z2Vub21lX3NwJG51bV9nZW5lcwpwYW5jYXRfYnlpc29fYnlnZW5vbWVfc3Akc2hlbGxfcHJvcCA9IHBhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCRzaGVsbC9wYW5jYXRfYnlpc29fYnlnZW5vbWVfc3AkbnVtX2dlbmVzCnBhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCRjbG91ZF9wcm9wID0gcGFuY2F0X2J5aXNvX2J5Z2Vub21lX3NwJGNsb3VkL3BhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCRudW1fZ2VuZXMKCnBhbmNhdF9ieWlzb19ieWdlbm9tZV9nYSA9IHBhbmNhdF9ieWlzb19ieWdlbm9tZV9zcCAlPiUgCiAgZ2F0aGVyKGNvcmVfcHJvcCwgc29mdGNvcmVfcHJvcCwgc2hlbGxfcHJvcCwgY2xvdWRfcHJvcCwga2V5ID0gInBhbl9jYXQiLCB2YWx1ZSA9ICJwcm9wb3J0aW9uIikgJT4lCiAgc2VsZWN0KC1jb3JlLCAtYHNvZnQgY29yZWAsIC1zaGVsbCwgLWNsb3VkKQoKcGFuY2F0X2J5aXNvX2J5Z2Vub21lX2dhJHBhbl9jYXQgPSBzdHJfcmVtb3ZlKHBhbmNhdF9ieWlzb19ieWdlbm9tZV9nYSRwYW5fY2F0LCAiX3Byb3AiKQpwYW5jYXRfYnlpc29fYnlnZW5vbWVfZ2EkcGFuX2NhdCA9IGZhY3RvcihwYW5jYXRfYnlpc29fYnlnZW5vbWVfZ2EkcGFuX2NhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvcmUiLCAic29mdGNvcmUiLCAic2hlbGwiLCAiY2xvdWQiKSkKCgooZ2VuZW51bV9pc28gPSBnZ3Bsb3QoZGF0YSA9IHBhbmNhdF9ieWlzb19ieWdlbm9tZV9nYSwgYWVzKHggPSBJU01FX3NvdXJjZSwgeT0gbnVtX2dlbmVzLCBjb2xvciA9IElTTUVfc291cmNlKSkgKyAKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwKSArIAogIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSksYWVzKGdyb3VwPUlTTUVfc291cmNlKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBJU01FY29sb3JzKSArCiAgI2ZhY2V0X2dyaWQoLn5wYW5fY2F0LCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9jbGFzc2ljKCkpCgoocGFuX3N0cl9pc28gPSBnZ3Bsb3QoZGF0YSA9IHBhbmNhdF9ieWlzb19ieWdlbm9tZV9nYSwgYWVzKHggPSBJU01FX3NvdXJjZSwgeT0gcHJvcG9ydGlvbiwgY29sb3IgPSBJU01FX3NvdXJjZSkpICsgCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMCkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpLGFlcyhncm91cD1JU01FX3NvdXJjZSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gSVNNRWNvbG9ycykgKwogIGZhY2V0X2dyaWQoLn5wYW5fY2F0LCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9jbGFzc2ljKCkpCgpzdGF0c19jb3JlID0gcGFuY2F0X2J5aXNvX2J5Z2Vub21lX2dhICU+JSBmaWx0ZXIocGFuX2NhdCA9PSAnY29yZScpCmtydXNrYWwudGVzdChwcm9wb3J0aW9uIH4gSVNNRV9zb3VyY2UsIGRhdGEgPSBzdGF0c19jb3JlKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gc3RhdHNfY29yZSRwcm9wb3J0aW9uLCBnID0gc3RhdHNfY29yZSRJU01FX3NvdXJjZSwgcC5hZGp1c3QubWV0aG9kID0gJ0JIJykKYWdncmVnYXRlKHN0YXRzX2NvcmUkcHJvcG9ydGlvbiwgYnkgPSBsaXN0KHN0YXRzX2NvcmUkSVNNRV9zb3VyY2UpLCBGVU4gPSBtZWRpYW4pCgpzdGF0c19zb2Z0Y29yZSA9IHBhbmNhdF9ieWlzb19ieWdlbm9tZV9nYSAlPiUgZmlsdGVyKHBhbl9jYXQgPT0gJ3NvZnRjb3JlJykKa3J1c2thbC50ZXN0KHByb3BvcnRpb24gfiBJU01FX3NvdXJjZSwgZGF0YSA9IHN0YXRzX3NvZnRjb3JlKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gc3RhdHNfc29mdGNvcmUkcHJvcG9ydGlvbiwgZyA9IHN0YXRzX3NvZnRjb3JlJElTTUVfc291cmNlLCBwLmFkanVzdC5tZXRob2QgPSAnQkgnKQphZ2dyZWdhdGUoc3RhdHNfc29mdGNvcmUkcHJvcG9ydGlvbiwgYnkgPSBsaXN0KHN0YXRzX3NvZnRjb3JlJElTTUVfc291cmNlKSwgRlVOID0gbWVkaWFuKQoKc3RhdHNfc2hlbGwgPSBwYW5jYXRfYnlpc29fYnlnZW5vbWVfZ2EgJT4lIGZpbHRlcihwYW5fY2F0ID09ICdzaGVsbCcpCmtydXNrYWwudGVzdChwcm9wb3J0aW9uIH4gSVNNRV9zb3VyY2UsIGRhdGEgPSBzdGF0c19zaGVsbCkKcGFpcndpc2Uud2lsY294LnRlc3QoeCA9IHN0YXRzX3NoZWxsJHByb3BvcnRpb24sIGcgPSBzdGF0c19zaGVsbCRJU01FX3NvdXJjZSwgcC5hZGp1c3QubWV0aG9kID0gJ0JIJykKYWdncmVnYXRlKHN0YXRzX3NoZWxsJHByb3BvcnRpb24sIGJ5ID0gbGlzdChzdGF0c19zaGVsbCRJU01FX3NvdXJjZSksIEZVTiA9IG1lZGlhbikKCnN0YXRzX2Nsb3VkID0gcGFuY2F0X2J5aXNvX2J5Z2Vub21lX2dhICU+JSBmaWx0ZXIocGFuX2NhdCA9PSAnY2xvdWQnKQprcnVza2FsLnRlc3QocHJvcG9ydGlvbiB+IElTTUVfc291cmNlLCBkYXRhID0gc3RhdHNfY2xvdWQpCnBhaXJ3aXNlLndpbGNveC50ZXN0KHggPSBzdGF0c19jbG91ZCRwcm9wb3J0aW9uLCBnID0gc3RhdHNfY2xvdWQkSVNNRV9zb3VyY2UsIHAuYWRqdXN0Lm1ldGhvZCA9ICdCSCcpCmFnZ3JlZ2F0ZShzdGF0c19jbG91ZCRwcm9wb3J0aW9uLCBieSA9IGxpc3Qoc3RhdHNfY2xvdWQkSVNNRV9zb3VyY2UpLCBGVU4gPSBtZWRpYW4pCgpgYGAKCiMjI0ZpZ3VyZSAzLjQgdW5pcXVlIGdlbmUgY29udGVudCBiZXR3ZWVuIGlzb2xhdGlvbiBzb3VyY2VzCmBgYHtyfQp3YXJtID0gcHN5Y2hfc3RyYWluX2NvbGxlY3Rpb24gJT4lIGZpbHRlcihJU01FX3NvdXJjZSA9PSAid2FybSBob3N0IikgJT4lIHNlbGVjdChzdHJhaW5JRCkgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUoKQpvdGhlciA9IHBzeWNoX3N0cmFpbl9jb2xsZWN0aW9uICU+JSBmaWx0ZXIoSVNNRV9zb3VyY2UgPT0gIm90aGVyIGhvc3QiKSAlPiUgc2VsZWN0KHN0cmFpbklEKSAlPiUgdW5saXN0KCkgJT4lIHVubmFtZSgpCmZvb2QgPSBwc3ljaF9zdHJhaW5fY29sbGVjdGlvbiAlPiUgZmlsdGVyKElTTUVfc291cmNlID09ICJmb29kIikgJT4lIHNlbGVjdChzdHJhaW5JRCkgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUoKQptYXJpbmUgPSBwc3ljaF9zdHJhaW5fY29sbGVjdGlvbiAlPiUgZmlsdGVyKElTTUVfc291cmNlID09ICJtYXJpbmUiKSAlPiUgc2VsZWN0KHN0cmFpbklEKSAlPiUgdW5saXN0KCkgJT4lIHVubmFtZSgpCnRlcnJlc3RyaWFsID0gcHN5Y2hfc3RyYWluX2NvbGxlY3Rpb24gJT4lIGZpbHRlcihJU01FX3NvdXJjZSA9PSAidGVycmVzdHJpYWwiKSAlPiUgc2VsZWN0KHN0cmFpbklEKSAlPiUgdW5saXN0KCkgJT4lIHVubmFtZSgpCgp3YXJtc2Vxc3VtID0gcm93U3VtcyhnZW5lc19tYXRfbnVtYmVyZWRbLGNvbG5hbWVzKGdlbmVzX21hdF9udW1iZXJlZCkgJWluJSB3YXJtXSkKbmFtZXMod2FybXNlcXN1bSkgPSByb3duYW1lcyhnZW5lc19tYXQpCndhcm1pc29zdW0gPSByb3dTdW1zKGdlbmVtYXRyaXhfYmluYXJ5Wyxjb2xuYW1lcyhnZW5lbWF0cml4X2JpbmFyeSkgJWluJSB3YXJtXSkKbmFtZXMod2FybWlzb3N1bSkgPSByb3duYW1lcyhnZW5lc19tYXQpCgpvdGhlcnNlcXN1bSA9IHJvd1N1bXMoZ2VuZXNfbWF0X251bWJlcmVkWyxjb2xuYW1lcyhnZW5lc19tYXRfbnVtYmVyZWQpICVpbiUgb3RoZXJdKQpuYW1lcyhvdGhlcnNlcXN1bSkgPSByb3duYW1lcyhnZW5lc19tYXQpCm90aGVyaXNvc3VtID0gcm93U3VtcyhnZW5lbWF0cml4X2JpbmFyeVssY29sbmFtZXMoZ2VuZW1hdHJpeF9iaW5hcnkpICVpbiUgb3RoZXJdKQpuYW1lcyhvdGhlcmlzb3N1bSkgPSByb3duYW1lcyhnZW5lc19tYXQpCgpmb29kc2Vxc3VtID0gcm93U3VtcyhnZW5lc19tYXRfbnVtYmVyZWRbLGNvbG5hbWVzKGdlbmVzX21hdF9udW1iZXJlZCkgJWluJSBmb29kXSkKbmFtZXMob3RoZXJzZXFzdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQpmb29kaXNvc3VtID0gcm93U3VtcyhnZW5lbWF0cml4X2JpbmFyeVssY29sbmFtZXMoZ2VuZW1hdHJpeF9iaW5hcnkpICVpbiUgZm9vZF0pCm5hbWVzKGZvb2Rpc29zdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQoKbWFyaW5lc2Vxc3VtID0gcm93U3VtcyhnZW5lc19tYXRfbnVtYmVyZWRbLGNvbG5hbWVzKGdlbmVzX21hdF9udW1iZXJlZCkgJWluJSBtYXJpbmVdKQpuYW1lcyhtYXJpbmVzZXFzdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQptYXJpbmVpc29zdW0gPSByb3dTdW1zKGdlbmVtYXRyaXhfYmluYXJ5Wyxjb2xuYW1lcyhnZW5lbWF0cml4X2JpbmFyeSkgJWluJSBtYXJpbmVdKQpuYW1lcyhtYXJpbmVpc29zdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQoKdGVycmVzdHJpYWxzZXFzdW0gPSByb3dTdW1zKGdlbmVzX21hdF9udW1iZXJlZFssY29sbmFtZXMoZ2VuZXNfbWF0X251bWJlcmVkKSAlaW4lIHRlcnJlc3RyaWFsXSkKbmFtZXModGVycmVzdHJpYWxzZXFzdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQp0ZXJyZXN0cmlhbGlzb3N1bSA9IHJvd1N1bXMoZ2VuZW1hdHJpeF9iaW5hcnlbLGNvbG5hbWVzKGdlbmVtYXRyaXhfYmluYXJ5KSAlaW4lIHRlcnJlc3RyaWFsXSkKbmFtZXModGVycmVzdHJpYWxpc29zdW0pID0gcm93bmFtZXMoZ2VuZXNfbWF0KQoKYWxsc2Vxc3VtID0gcm93U3VtcyhnZW5lc19tYXRfbnVtYmVyZWQpCm5hbWVzKGFsbHNlcXN1bSkgPSByb3duYW1lcyhnZW5lc19tYXQpCmFsbGlzb3N1bSA9IHJvd1N1bXMoZ2VuZW1hdHJpeF9iaW5hcnkpCm5hbWVzKGFsbGlzb3N1bSkgPSByb3duYW1lcyhnZW5lc19tYXQpCgpwYW5fc3RyX2lzbyA9IHJiaW5kKGFsbHNlcXN1bSwgYWxsaXNvc3VtLCB3YXJtc2Vxc3VtLCB3YXJtaXNvc3VtLCBvdGhlcnNlcXN1bSwgb3RoZXJpc29zdW0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb29kc2Vxc3VtLCBmb29kaXNvc3VtLCBtYXJpbmVzZXFzdW0sIG1hcmluZWlzb3N1bSwgdGVycmVzdHJpYWxzZXFzdW0sIHRlcnJlc3RyaWFsaXNvc3VtKQoKcGFuX3N0cl9pc28gPSB0KHBhbl9zdHJfaXNvKQpwYW5fc3RyX2lzbyA9IGFzLmRhdGEuZnJhbWUocGFuX3N0cl9pc28pCnBhbl9zdHJfaXNvJGdlbmVDbHVzdGVyID0gcm93bmFtZXMocGFuX3N0cl9pc28pCgoKcGFuX3N0cl9pc28kb3ZlcmFsbF9wYW5fY2F0ID0gTkEKcGFuX3N0cl9pc28kb3ZlcmFsbF9wYW5fY2F0W3Bhbl9zdHJfaXNvJGFsbGlzb3N1bSA+PSA4NF0gPC0gImNvcmUiCnBhbl9zdHJfaXNvJG92ZXJhbGxfcGFuX2NhdFtwYW5fc3RyX2lzbyRhbGxpc29zdW0gPD0gODMgJiBwYW5fc3RyX2lzbyRhbGxpc29zdW0gPj0gNzddIDwtICJzb2Z0IGNvcmUiCnBhbl9zdHJfaXNvJG92ZXJhbGxfcGFuX2NhdFtwYW5fc3RyX2lzbyRhbGxpc29zdW0gPD0gODIgJiBwYW5fc3RyX2lzbyRhbGxpc29zdW0gPj0gMiBdIDwtICJzaGVsbCIKcGFuX3N0cl9pc28kb3ZlcmFsbF9wYW5fY2F0W3Bhbl9zdHJfaXNvJGFsbGlzb3N1bSA9PSAxIF0gPC0gImNsb3VkIgoKcGFuX3N0cl9pc28kd2FybV9wYW5fY2F0ID0gTkEKcGFuX3N0cl9pc28kd2FybV9wYW5fY2F0W3Bhbl9zdHJfaXNvJHdhcm1pc29zdW0gPj0gMTNdIDwtICJjb3JlIgpwYW5fc3RyX2lzbyR3YXJtX3Bhbl9jYXRbcGFuX3N0cl9pc28kd2FybWlzb3N1bSA8PSAxMiAmIHBhbl9zdHJfaXNvJHdhcm1pc29zdW0gPj0gMiBdIDwtICJzaGVsbCIKcGFuX3N0cl9pc28kd2FybV9wYW5fY2F0W3Bhbl9zdHJfaXNvJHdhcm1pc29zdW0gPT0gMSBdIDwtICJjbG91ZCIKcGFuX3N0cl9pc28kd2FybV9wYW5fY2F0W3Bhbl9zdHJfaXNvJHdhcm1pc29zdW0gPT0gMCBdIDwtICJhYnNlbnQiCgpwYW5fc3RyX2lzbyRvdGhlcl9wYW5fY2F0ID0gTkEKcGFuX3N0cl9pc28kb3RoZXJfcGFuX2NhdFtwYW5fc3RyX2lzbyRvdGhlcmlzb3N1bSA+PSAyMF0gPC0gImNvcmUiCnBhbl9zdHJfaXNvJG90aGVyX3Bhbl9jYXRbcGFuX3N0cl9pc28kb3RoZXJpc29zdW0gPD0gMTkgJiBwYW5fc3RyX2lzbyRvdGhlcmlzb3N1bSA+PSAyIF0gPC0gInNoZWxsIgpwYW5fc3RyX2lzbyRvdGhlcl9wYW5fY2F0W3Bhbl9zdHJfaXNvJG90aGVyaXNvc3VtID09IDEgXSA8LSAiY2xvdWQiCnBhbl9zdHJfaXNvJG90aGVyX3Bhbl9jYXRbcGFuX3N0cl9pc28kb3RoZXJpc29zdW0gPT0gMCBdIDwtICJhYnNlbnQiCgpwYW5fc3RyX2lzbyRmb29kX3Bhbl9jYXQgPSBOQQpwYW5fc3RyX2lzbyRmb29kX3Bhbl9jYXRbcGFuX3N0cl9pc28kZm9vZGlzb3N1bSA9PSAxMV0gPC0gImNvcmUiCnBhbl9zdHJfaXNvJGZvb2RfcGFuX2NhdFtwYW5fc3RyX2lzbyRmb29kaXNvc3VtIDw9IDEwICYgcGFuX3N0cl9pc28kZm9vZGlzb3N1bSA+PSAyIF0gPC0gInNoZWxsIgpwYW5fc3RyX2lzbyRmb29kX3Bhbl9jYXRbcGFuX3N0cl9pc28kZm9vZGlzb3N1bSA9PSAxIF0gPC0gImNsb3VkIgpwYW5fc3RyX2lzbyRmb29kX3Bhbl9jYXRbcGFuX3N0cl9pc28kZm9vZGlzb3N1bSA9PSAwIF0gPC0gImFic2VudCIKCnBhbl9zdHJfaXNvJG1hcmluZV9wYW5fY2F0ID0gTkEKcGFuX3N0cl9pc28kbWFyaW5lX3Bhbl9jYXRbcGFuX3N0cl9pc28kbWFyaW5laXNvc3VtID49IDE5XSA8LSAiY29yZSIKcGFuX3N0cl9pc28kbWFyaW5lX3Bhbl9jYXRbcGFuX3N0cl9pc28kbWFyaW5laXNvc3VtIDw9IDE4ICYgcGFuX3N0cl9pc28kbWFyaW5laXNvc3VtID49IDIgXSA8LSAic2hlbGwiCnBhbl9zdHJfaXNvJG1hcmluZV9wYW5fY2F0W3Bhbl9zdHJfaXNvJG1hcmluZWlzb3N1bSA9PSAxIF0gPC0gImNsb3VkIgpwYW5fc3RyX2lzbyRtYXJpbmVfcGFuX2NhdFtwYW5fc3RyX2lzbyRtYXJpbmVpc29zdW0gPT0gMCBdIDwtICJhYnNlbnQiCgpwYW5fc3RyX2lzbyR0ZXJyZXN0cmlhbF9wYW5fY2F0ID0gTkEKcGFuX3N0cl9pc28kdGVycmVzdHJpYWxfcGFuX2NhdFtwYW5fc3RyX2lzbyR0ZXJyZXN0cmlhbGlzb3N1bSA+PSAxNV0gPC0gImNvcmUiCnBhbl9zdHJfaXNvJHRlcnJlc3RyaWFsX3Bhbl9jYXRbcGFuX3N0cl9pc28kdGVycmVzdHJpYWxpc29zdW0gPD0gMTQgJiBwYW5fc3RyX2lzbyR0ZXJyZXN0cmlhbGlzb3N1bSA+PSAyIF0gPC0gInNoZWxsIgpwYW5fc3RyX2lzbyR0ZXJyZXN0cmlhbF9wYW5fY2F0W3Bhbl9zdHJfaXNvJHRlcnJlc3RyaWFsaXNvc3VtID09IDEgXSA8LSAiY2xvdWQiCnBhbl9zdHJfaXNvJHRlcnJlc3RyaWFsX3Bhbl9jYXRbcGFuX3N0cl9pc28kdGVycmVzdHJpYWxpc29zdW0gPT0gMCBdIDwtICJhYnNlbnQiCgp1bmlxdWVfd2FybSA9IHBhbl9zdHJfaXNvICU+JSBmaWx0ZXIod2FybV9wYW5fY2F0ICE9ICJhYnNlbnQiICYgb3RoZXJfcGFuX2NhdCA9PSAiYWJzZW50IiAmIGZvb2RfcGFuX2NhdCA9PSAiYWJzZW50IiAmIG1hcmluZV9wYW5fY2F0ID09ICJhYnNlbnQiICYgdGVycmVzdHJpYWxfcGFuX2NhdCA9PSAiYWJzZW50IikgJT4lIHNlbGVjdChnZW5lQ2x1c3RlcikgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUKdW5pcXVlX3dhcm1fYW5ub3QgPSBtdWx0aUNPR19nZW5lc19jb3JyZWN0ZWQgJT4lIGZpbHRlcihnZW5lQ2x1c3RlciAlaW4lIHVuaXF1ZV93YXJtKQp1bmlxdWVfd2FybV9hbm5vdCRpc29sYXRpb24gPSAid2FybSIKCnVuaXF1ZV9vdGhlciA9IHBhbl9zdHJfaXNvICU+JSBmaWx0ZXIod2FybV9wYW5fY2F0ID09ICJhYnNlbnQiICYgb3RoZXJfcGFuX2NhdCAhPSAiYWJzZW50IiAmIGZvb2RfcGFuX2NhdCA9PSAiYWJzZW50IiAmIG1hcmluZV9wYW5fY2F0ID09ICJhYnNlbnQiICYgdGVycmVzdHJpYWxfcGFuX2NhdCA9PSAiYWJzZW50IikgJT4lIHNlbGVjdChnZW5lQ2x1c3RlcikgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUKdW5pcXVlX290aGVyX2Fubm90ID0gbXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkICU+JSBmaWx0ZXIoZ2VuZUNsdXN0ZXIgJWluJSB1bmlxdWVfb3RoZXIpCnVuaXF1ZV9vdGhlcl9hbm5vdCRpc29sYXRpb24gPSAib3RoZXIiCgp1bmlxdWVfZm9vZCA9IHBhbl9zdHJfaXNvICU+JSBmaWx0ZXIod2FybV9wYW5fY2F0ID09ICJhYnNlbnQiICYgb3RoZXJfcGFuX2NhdCA9PSAiYWJzZW50IiAmIGZvb2RfcGFuX2NhdCAhPSAiYWJzZW50IiAmIG1hcmluZV9wYW5fY2F0ID09ICJhYnNlbnQiICYgdGVycmVzdHJpYWxfcGFuX2NhdCA9PSAiYWJzZW50IikgJT4lIHNlbGVjdChnZW5lQ2x1c3RlcikgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUKdW5pcXVlX2Zvb2RfYW5ub3QgPSBtdWx0aUNPR19nZW5lc19jb3JyZWN0ZWQgJT4lIGZpbHRlcihnZW5lQ2x1c3RlciAlaW4lIHVuaXF1ZV9mb29kKQp1bmlxdWVfZm9vZF9hbm5vdCRpc29sYXRpb24gPSAiZm9vZCIKCnVuaXF1ZV9tYXJpbmUgPSBwYW5fc3RyX2lzbyAlPiUgZmlsdGVyKHdhcm1fcGFuX2NhdCA9PSAiYWJzZW50IiAmIG90aGVyX3Bhbl9jYXQgPT0gImFic2VudCIgJiBmb29kX3Bhbl9jYXQgPT0gImFic2VudCIgJiBtYXJpbmVfcGFuX2NhdCAhPSAiYWJzZW50IiAmIHRlcnJlc3RyaWFsX3Bhbl9jYXQgPT0gImFic2VudCIpICU+JSBzZWxlY3QoZ2VuZUNsdXN0ZXIpICU+JSB1bmxpc3QoKSAlPiUgdW5uYW1lCnVuaXF1ZV9tYXJpbmVfYW5ub3QgPSBtdWx0aUNPR19nZW5lc19jb3JyZWN0ZWQgJT4lIGZpbHRlcihnZW5lQ2x1c3RlciAlaW4lIHVuaXF1ZV9tYXJpbmUpCnVuaXF1ZV9tYXJpbmVfYW5ub3QkaXNvbGF0aW9uID0gIm1hcmluZSIKCnVuaXF1ZV90ZXJyZXN0cmlhbCA9IHBhbl9zdHJfaXNvICU+JSBmaWx0ZXIod2FybV9wYW5fY2F0ID09ICJhYnNlbnQiICYgb3RoZXJfcGFuX2NhdCA9PSAiYWJzZW50IiAmIGZvb2RfcGFuX2NhdCA9PSAiYWJzZW50IiAmIG1hcmluZV9wYW5fY2F0ID09ICJhYnNlbnQiICYgdGVycmVzdHJpYWxfcGFuX2NhdCAhPSAiYWJzZW50IikgJT4lIHNlbGVjdChnZW5lQ2x1c3RlcikgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUKdW5pcXVlX3RlcnJlc3RyaWFsX2Fubm90ID0gbXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkICU+JSBmaWx0ZXIoZ2VuZUNsdXN0ZXIgJWluJSB1bmlxdWVfdGVycmVzdHJpYWwpCnVuaXF1ZV90ZXJyZXN0cmlhbF9hbm5vdCRpc29sYXRpb24gPSAidGVycmVzdHJpYWwiCgp1bmlxdWVfZ2VuZXNfcGVyX2lzb2xhdGlvbiA9IHJiaW5kKHVuaXF1ZV93YXJtX2Fubm90LCB1bmlxdWVfb3RoZXJfYW5ub3QsIHVuaXF1ZV9mb29kX2Fubm90LCB1bmlxdWVfbWFyaW5lX2Fubm90LCB1bmlxdWVfdGVycmVzdHJpYWxfYW5ub3QpCgp1bmlxdWVfZ2VuZXNfcGVyX2lzb2xhdGlvbiRpc29sYXRpb24gPSBmYWN0b3IodW5pcXVlX2dlbmVzX3Blcl9pc29sYXRpb24kaXNvbGF0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtIiwgIm90aGVyIiwgImZvb2QiLCAibWFyaW5lIiwgInRlcnJlc3RyaWFsIikpCnVuaXF1ZV9nZW5lc19wZXJfaXNvbGF0aW9uJENPR19jYXRlZ29yeSA9IGZhY3Rvcih1bmlxdWVfZ2VuZXNfcGVyX2lzb2xhdGlvbiRDT0dfY2F0ZWdvcnksIGxldmVscyA9IGMoIkQiLCAiTSIsICJOIiwgIk8iLCAiVCIsICJVIiwgIlYiLCAiVyIsICJaIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkEiLCAiQiIsIkoiLCAiSyIsICJMIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIlAiLCAiUSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTIiwgIlgiKSkKY29scyA9IGMoIiM3MjMwMEMiLCAiIzkzMDc0RCIsICIjRDYwRDY5IiwgIiNFRDVGQTYiLCAiI0NFMUIxMyIsICIjQTUwNTA1IiwKICAgICAgICAgIiNFNTUzMEEiLCAiI0UyNzcwQyIsICIjRjlBMTM4IiwgIiNGN0YwNzIiLCAiI0Y3RDIzOSIsICIjQ0NGNDNCIiwKICAgICAgICAgIiM1QkI3M0QiLCAiIzA1N0YyOCIsICIjMDU1NDFBIiwgIiMyMDk5OEIiLCAiIzYwQjFGNCIsICIjMTQ1OEYyIiwKICAgICAgICAgIiM1MTQxQUYiLCAiIzFGMDQ4RSIsICIjMzEwODcyIiwgIiM1MjA3NzUiLCAiIzlGOUZBMCIsICIjMzkzODNBIikKCih1bmlxdWVfZ2VuZV9jb250ZW50ID0gZ2dwbG90KGRhdGEgPSB1bmlxdWVfZ2VuZXNfcGVyX2lzb2xhdGlvbiwgYWVzKHggPSBpc29sYXRpb24sIGZpbGwgPSBDT0dfY2F0ZWdvcnkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdjb3VudCcpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xzKSArCiAgdGhlbWVfY2xhc3NpYygpKQoKdW5pcXVlX2NvcnIgPSB0YWJsZSh1bmlxdWVfZ2VuZXNfcGVyX2lzb2xhdGlvbiRpc29sYXRpb24sIHVuaXF1ZV9nZW5lc19wZXJfaXNvbGF0aW9uJENPR19jYXRlZ29yeSkKY2hpc3FfdW5pX2lzbyA9IGNoaXNxLnRlc3QodW5pcXVlX2NvcnIpCmNvcnJwbG90KGNoaXNxX3VuaV9pc28kcmVzaWR1YWxzLCBpcy5jb3JyID0gRikKCiNhZGQgdW5pcXVlX2dlbmVfY29udGVudCB3IGNvcnJwbG90IGluIGlsbHVzdHJhdG9yCgpgYGAKCiNQYW4tZ2Vub21lIHdpZGUgYXNzb2NpYXRpb24gc3R1ZHkgd2l0aCBpc29sYXRpb24gc291cmNlIGFzIHRyYWl0LiAKYGBge3J9CnVuaXF1ZShwc3ljaF9zdHJhaW5fY29sbGVjdGlvbiRJU01FX3NvdXJjZSkKCmlzb2xhdGlvbnNvdXJjZSA9IHBzeWNoX3N0cmFpbl9jb2xsZWN0aW9uWyxjKDMsMjcpXQppc29sYXRpb25zb3VyY2UkZHVtbXkgPSAxCmlzb2xhdGlvbnNvdXJjZSA9IGlzb2xhdGlvbnNvdXJjZSAlPiUKICBzcHJlYWQoa2V5ID0gSVNNRV9zb3VyY2UsIHZhbHVlID0gZHVtbXkpCmlzb2xhdGlvbnNvdXJjZVtpcy5uYShpc29sYXRpb25zb3VyY2UpXSA8LSAwCnJvd25hbWVzKGlzb2xhdGlvbnNvdXJjZSkgPSBpc29sYXRpb25zb3VyY2Ukc3RyYWluSUQKCldIIDwtIGFzLnZlY3Rvcih1bmxpc3QoaXNvbGF0aW9uc291cmNlJGB3YXJtIGhvc3RgKSkKbmFtZXMoV0gpID0gcm93bmFtZXMoaXNvbGF0aW9uc291cmNlKQphbGwobmFtZXMoV0gpICVpbiUgcm93bmFtZXMoZ2VuZW1hdHJpeF90cmVld2FzKSkKYWxsKHJvd25hbWVzKGdlbmVtYXRyaXhfdHJlZXdhcykgJWluJSBuYW1lcyhXSCkpCldIX3RyZWV3YXMgPC0gdHJlZVdBUyhzbnBzID0gZ2VuZW1hdHJpeF90cmVld2FzLCBwaGVuID0gV0gsIHRyZWUgPSBQLnRyZWUubm9vdXQsIHNlZWQgPSAxKQpwcmludChXSF90cmVld2FzKQoKT0ggPC0gYXMudmVjdG9yKHVubGlzdChpc29sYXRpb25zb3VyY2UkYG90aGVyIGhvc3RgKSkKbmFtZXMoT0gpID0gcm93bmFtZXMoaXNvbGF0aW9uc291cmNlKQphbGwobmFtZXMoT0gpICVpbiUgcm93bmFtZXMoZ2VuZW1hdHJpeF90cmVld2FzKSkKYWxsKHJvd25hbWVzKGdlbmVtYXRyaXhfdHJlZXdhcykgJWluJSBuYW1lcyhPSCkpCk9IX3RyZWV3YXMgPC0gdHJlZVdBUyhzbnBzID0gZ2VuZW1hdHJpeF90cmVld2FzLCBwaGVuID0gT0gsIHRyZWUgPSBQLnRyZWUubm9vdXQsIHNlZWQgPSAxKQpwcmludChPSF90cmVld2FzKQoKRm8gPC0gYXMudmVjdG9yKHVubGlzdChpc29sYXRpb25zb3VyY2UkZm9vZCkpCm5hbWVzKEZvKSA9IHJvd25hbWVzKGlzb2xhdGlvbnNvdXJjZSkKYWxsKG5hbWVzKEZvKSAlaW4lIHJvd25hbWVzKGdlbmVtYXRyaXhfdHJlZXdhcykpCmFsbChyb3duYW1lcyhnZW5lbWF0cml4X3RyZWV3YXMpICVpbiUgbmFtZXMoRm8pKQpGb190cmVld2FzIDwtIHRyZWVXQVMoc25wcyA9IGdlbmVtYXRyaXhfdHJlZXdhcywgcGhlbiA9IEZvLCB0cmVlID0gUC50cmVlLm5vb3V0LCBzZWVkID0gMSkKcHJpbnQoRm9fdHJlZXdhcykKCk1hIDwtIGFzLnZlY3Rvcih1bmxpc3QoaXNvbGF0aW9uc291cmNlJG1hcmluZSkpCm5hbWVzKE1hKSA9IHJvd25hbWVzKGlzb2xhdGlvbnNvdXJjZSkKYWxsKG5hbWVzKE1hKSAlaW4lIHJvd25hbWVzKGdlbmVtYXRyaXhfdHJlZXdhcykpCmFsbChyb3duYW1lcyhnZW5lbWF0cml4X3RyZWV3YXMpICVpbiUgbmFtZXMoTWEpKQpNYV90cmVld2FzIDwtIHRyZWVXQVMoc25wcyA9IGdlbmVtYXRyaXhfdHJlZXdhcywgcGhlbiA9IE1hLCB0cmVlID0gUC50cmVlLm5vb3V0LCBzZWVkID0gMSkKcHJpbnQoTWFfdHJlZXdhcykKClRlIDwtIGFzLnZlY3Rvcih1bmxpc3QoaXNvbGF0aW9uc291cmNlJHRlcnJlc3RyaWFsKSkKbmFtZXMoVGUpID0gcm93bmFtZXMoaXNvbGF0aW9uc291cmNlKQphbGwobmFtZXMoVGUpICVpbiUgcm93bmFtZXMoZ2VuZW1hdHJpeF90cmVld2FzKSkKYWxsKHJvd25hbWVzKGdlbmVtYXRyaXhfdHJlZXdhcykgJWluJSBuYW1lcyhUZSkpClRlX3RyZWV3YXMgPC0gdHJlZVdBUyhzbnBzID0gZ2VuZW1hdHJpeF90cmVld2FzLCBwaGVuID0gVGUsIHRyZWUgPSBQLnRyZWUubm9vdXQsIHNlZWQgPSAxKQpwcmludChUZV90cmVld2FzKQoKT0hfdHJlZXdhc19nYyA9IE9IX3RyZWV3YXMkdHJlZVdBUy5jb21iaW5lZCR0cmVlV0FTLmNvbWJpbmVkICU+JSB1bmxpc3QoKQpPSF90cmVld2FzX2Fubm90YXRlZCA9IHBzeWNoX2VnZ25vZ19hbm5vdGF0aW9ucyAlPiUgZmlsdGVyKGdlbmVDbHVzdGVyICVpbiUgT0hfdHJlZXdhc19nYykKCkZvX3RyZWV3YXNfZ2MgPSBGb190cmVld2FzJHRyZWVXQVMuY29tYmluZWQkdHJlZVdBUy5jb21iaW5lZCAlPiUgdW5saXN0KCkKRm9fdHJlZXdhc19hbm5vdGF0ZWQgPSBwc3ljaF9lZ2dub2dfYW5ub3RhdGlvbnMgJT4lIGZpbHRlcihnZW5lQ2x1c3RlciAlaW4lIEZvX3RyZWV3YXNfZ2MpCgpNYV90cmVld2FzX2djID0gTWFfdHJlZXdhcyR0cmVlV0FTLmNvbWJpbmVkJHRyZWVXQVMuY29tYmluZWQgJT4lIHVubGlzdCgpCk1hX3RyZWV3YXNfYW5ub3RhdGVkID0gcHN5Y2hfZWdnbm9nX2Fubm90YXRpb25zICU+JSBmaWx0ZXIoZ2VuZUNsdXN0ZXIgJWluJSBNYV90cmVld2FzX2djKQoKVGVfdHJlZXdhc19nYyA9IFRlX3RyZWV3YXMkdHJlZVdBUy5jb21iaW5lZCR0cmVlV0FTLmNvbWJpbmVkICU+JSB1bmxpc3QoKQpUZV90cmVld2FzX2Fubm90YXRlZCA9IHBzeWNoX2VnZ25vZ19hbm5vdGF0aW9ucyAlPiUgZmlsdGVyKGdlbmVDbHVzdGVyICVpbiUgVGVfdHJlZXdhc19nYykKCmBgYAoKI0lzb2xhdGlvbiBzb3VyY2UgYW5jZXN0cmFsIGNoYXJhY3RlciBlc3RpbWF0aW9uLgoKYGBge3J9CgojdHdvIHN0YXRlIGFuY2VzdHJhbCBzdGF0ZSByZWNvbnN0cnVjdGlvbgpvcmRlcmVkX2RmID0gc3RyYWluX2NvbGxlY3Rpb25bbWF0Y2goTS50cmVlJHRpcC5sYWJlbCwgc3RyYWluX2NvbGxlY3Rpb24kc3RyYWluSUQpLF0Kcm93bmFtZXMob3JkZXJlZF9kZikgPSBvcmRlcmVkX2RmJHN0cmFpbklECngxPC1zZXROYW1lcyhvcmRlcmVkX2RmWywyMV0scm93bmFtZXMob3JkZXJlZF9kZikpCngxY29sID0gYygiZGVlcHNreWJsdWUzIiwgIm9yYW5nZSIpCgpmaXRFUjEgPSBhY2UoeDEsIE0udHJlZSwgbW9kZWwgPSAiRVIiLCB0eXBlID0gImRpc2NyZXRlIiwgbWFyZ2luYWwgPSBUUlVFKQpmaXRTWU0xID0gYWNlKHgxLCBNLnRyZWUsIG1vZGVsID0gIlNZTSIsIHR5cGUgPSAiZGlzY3JldGUiLCBtYXJnaW5hbCA9IFRSVUUpCmZpdEFSRDEgPSBhY2UoeDEsIE0udHJlZSwgbW9kZWwgPSAiQVJEIiwgdHlwZSA9ICJkaXNjcmV0ZSIsIG1hcmdpbmFsID0gVFJVRSkKCiNBUkQgbW9kZWwgbWF4aW1pemVzIGxpa2VsaWhvb2QsIGJ1dCBkb2VzIGl0IGRvIHNvIHNpZ25pZmljYW50bHk/CjEgLSBwY2hpc3EoMiphYnMoZml0QVJEMSRsb2dsaWsgLSBmaXRFUjEkbG9nbGlrKSwgMSkgI3AgPSAwLjE1CjEgLSBwY2hpc3EoMiphYnMoZml0QVJEMSRsb2dsaWsgLSBmaXRTWU0xJGxvZ2xpayksIDEpICNwID0gMC4xNQoKI29rLCBzbyBpcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiBFUiBhbmQgU1lNPwoxIC0gcGNoaXNxKDIqYWJzKGZpdEVSMSRsb2dsaWsgLSBmaXRTWU0xJGxvZ2xpayksIDEpCiNubwojc28gSSB3aWxsIGdvIHdpdGggdGhlIHNpbXBsZXN0IEVSIG1vZGVsCgpwbG90VHJlZShNLnRyZWUsZnNpemU9MC44LGZ0eXBlPSJpIikKbm9kZWxhYmVscyhub2RlPTE6TS50cmVlJE5ub2RlK050aXAoTS50cmVlKSxwaWU9Zml0RVIxJGxpay5hbmMscGllY29sID0geDFjb2wsY2V4PTAuNSkKI3RpcGxhYmVscyhwaWU9dG8ubWF0cml4KHgxW00udHJlZSR0aXAubGFiZWxdLGxldmVscyh4MSkpLHBpZWNvbCA9IHgxY29sLGNleD0wLjMpCiNhZGQuc2ltbWFwLmxlZ2VuZChsZWc9c29ydCh1bmlxdWUoeDEpKSxjb2xvcnM9eDFjb2wseD0wLjkqcGFyKCkkdXNyWzFdLAojICAgICAgICAgICAgICAgICAgeT0tbWF4KG5vZGVIZWlnaHRzKE0udHJlZSkpLGZzaXplPTAuOCkKCiNwbG90VHJlZShNLnRyZWUsZnNpemU9MC44LGZ0eXBlPSJpIikKdGlwbGFiZWxzKHBpZT10by5tYXRyaXgoeDEsc29ydCh1bmlxdWUoeDEpKSkscGllY29sPXgxY29sLGNleD0wLjMpCmFkZC5zaW1tYXAubGVnZW5kKGNvbG9ycz14MWNvbCxwcm9tcHQ9RkFMU0UseD0wLjkqcGFyKCkkdXNyWzFdLAogICAgICAgICAgICAgICAgICB5PS1tYXgobm9kZUhlaWdodHMoTS50cmVlKSksZnNpemU9MC44KQoKZml0RVIxCgpwc3ljaHJvb3QgPSBkcm9wLnRpcChNLnRyZWUsIGMoIk1fYm9ldnJlaSIsIk1fYXRsYW50YWUiLCJNX29zbG9lbnNpcyIsIkFfcHV5YW5nZW5zaXMiLAogICAgICAgICAgICAgICAgICAgICAiTV9jdW5pY3VsaSIsIk1fcG9yY2kiLCJNX3BsdXJhbmltYWxpdW0iLCJNX2NhbmlzIiwiTV9jYXRhcnJoYWxpcyIsIk1fY2F2aWFlIiwKICAgICAgICAgICAgICAgICAgICAgIk1fb3ZpcyIsIk1fYm92b2N1bGkiLCJNX29ibG9uZ2EiLCJNX2VxdWkiLCJNX2JvdmlzIiwiTV9jYXByYWUiLCJNX2xhY3VuYXRhIiwiTV9ub25saXF1ZWZhY2llbnMiKSkKCgp4MXBzeWNocm9vdDwteDFbbmFtZXMoeDEpICVpbiUgcHN5Y2hyb290JHRpcC5sYWJlbF0KZml0RVJfcHN5Y2hyb290ID0gYWNlKHgxcHN5Y2hyb290LCBwc3ljaHJvb3QsIG1vZGVsID0gIkVSIiwgdHlwZSA9ICJkaXNjcmV0ZSIsIG1hcmdpbmFsID0gVFJVRSkKCmZpdEVSX3BzeWNocm9vdAoKcGxvdFRyZWUocHN5Y2hyb290LGZzaXplPTAuOCxmdHlwZT0iaSIpCm5vZGVsYWJlbHMobm9kZT0xOnBzeWNocm9vdCRObm9kZStOdGlwKHBzeWNocm9vdCkscGllPWZpdEVSX3BzeWNocm9vdCRsaWsuYW5jLHBpZWNvbCA9IHgxY29sLGNleD0wLjUpCiN0aXBsYWJlbHMocGllPXRvLm1hdHJpeCh4MXBzeWNocm9vdFtwc3ljaHJvb3QkdGlwLmxhYmVsXSxsZXZlbHMoeDFwc3ljaHJvb3QpKSxwaWVjb2wgPSB4MWNvbCxjZXg9MC4zKQojYWRkLnNpbW1hcC5sZWdlbmQobGVnPXNvcnQodW5pcXVlKHgxcHN5Y2hyb290KSksY29sb3JzPXgxY29sLHg9MC45KnBhcigpJHVzclsxXSwKIyAgICAgICAgICAgICAgICAgIHk9LW1heChub2RlSGVpZ2h0cyhwc3ljaHJvb3QpKSxmc2l6ZT0wLjgpCgojcGxvdFRyZWUoTS50cmVlLGZzaXplPTAuOCxmdHlwZT0iaSIpCnRpcGxhYmVscyhwaWU9dG8ubWF0cml4KHgxcHN5Y2hyb290LHNvcnQodW5pcXVlKHgxcHN5Y2hyb290KSkpLHBpZWNvbD14MWNvbCxjZXg9MC4zKQphZGQuc2ltbWFwLmxlZ2VuZChjb2xvcnM9eDFjb2wscHJvbXB0PUZBTFNFLHg9MC45KnBhcigpJHVzclsxXSwKICAgICAgICAgICAgICAgICAgeT0tbWF4KG5vZGVIZWlnaHRzKHBzeWNocm9vdCkpLGZzaXplPTAuOCkKCgojbm93IGJ5IG1vcmUgc3BlY2lmaWMgaXNvbGF0aW9uIHNvdXJjZXMgCm9yZGVyZWRfZGYkSVNNRV9zb3VyY2UgPSBmYWN0b3Iob3JkZXJlZF9kZiRJU01FX3NvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJ3YXJtIGhvc3QiLCAib3RoZXIgaG9zdCIsICJmb29kIiwgIm1hcmluZSIsICJ0ZXJyZXN0cmlhbCIpKQp4Mjwtc2V0TmFtZXMob3JkZXJlZF9kZlssMTldLHJvd25hbWVzKG9yZGVyZWRfZGYpKQp4MmNvbCA9IGMoIiNGOUQ1MDMiLCAiIzVEQzg2MyIsICIjMjE5MDhDIiwgIiMzQjUyOEIiLCAiIzQ0MDE1NCIpCgpmaXRFUjIgPSBhY2UoeDIsIE0udHJlZSwgbW9kZWwgPSAiRVIiLCB0eXBlID0gImRpc2NyZXRlIiwgbWFyZ2luYWwgPSBUUlVFKQpmaXRTWU0yID0gYWNlKHgyLCBNLnRyZWUsIG1vZGVsID0gIlNZTSIsIHR5cGUgPSAiZGlzY3JldGUiLCBtYXJnaW5hbCA9IFRSVUUpCmZpdEFSRDIgPSBhY2UoeDIsIE0udHJlZSwgbW9kZWwgPSAiQVJEIiwgdHlwZSA9ICJkaXNjcmV0ZSIsIG1hcmdpbmFsID0gVFJVRSkKCiNBUkQgbW9kZWwgbWF4aW1pemVzIGxpa2VsaWhvb2QsIGJ1dCBkb2VzIGl0IGRvIHNvIHNpZ25pZmljYW50bHk/CjEgLSBwY2hpc3EoMiphYnMoZml0QVJEMiRsb2dsaWsgLSBmaXRFUjIkbG9nbGlrKSwgMSkgI3AgPSAxLjExMDIyM2UtMTUKMSAtIHBjaGlzcSgyKmFicyhmaXRBUkQyJGxvZ2xpayAtIGZpdFNZTTIkbG9nbGlrKSwgMSkgI3AgPSA0LjI2MDM3NmUtMDUKCiNib3RoIHNpZ25pZmljYW50LCBzbwojSSB3aWxsIGdvIHdpdGggdGhlIEFSRCBtb2RlbAoKMSAtIHBjaGlzcSgyKmFicyhmaXRTWU0yJGxvZ2xpayAtIGZpdEVSMiRsb2dsaWspLCAxKQoKcGxvdFRyZWUoTS50cmVlLGZzaXplPTAuOCxmdHlwZT0iaSIpCnRpcGxhYmVscyhwaWU9dG8ubWF0cml4KHgyLHNvcnQodW5pcXVlKHgyKSkpLHBpZWNvbD14MmNvbCxjZXg9MC4zKQphZGQuc2ltbWFwLmxlZ2VuZChjb2xvcnM9eDJjb2wscHJvbXB0PUZBTFNFLHg9MC45KnBhcigpJHVzclsxXSwKICAgICAgICAgICAgICAgICAgeT0tbWF4KG5vZGVIZWlnaHRzKE0udHJlZSkpLGZzaXplPTAuOCkKCiNwbG90VHJlZShNLnRyZWUsZnNpemU9MC44LGZ0eXBlPSJpIikKbm9kZWxhYmVscyhub2RlPTE6TS50cmVlJE5ub2RlK050aXAoTS50cmVlKSxwaWU9Zml0RVIyJGxpay5hbmMscGllY29sID0geDJjb2wsY2V4PTAuNSkKI3RpcGxhYmVscyhwaWU9dG8ubWF0cml4KHgyW00udHJlZSR0aXAubGFiZWxdLGxldmVscyh4MikpLHBpZWNvbCA9IHgyY29sLGNleD0wLjMpCiNhZGQuc2ltbWFwLmxlZ2VuZChsZWc9c29ydCh1bmlxdWUoeDIpKSxjb2xvcnM9eDJjb2wseD0wLjkqcGFyKCkkdXNyWzFdLAojICAgICAgICAgICAgICAgICAgeT0tbWF4KG5vZGVIZWlnaHRzKE0udHJlZSkpLGZzaXplPTAuOCkKCngycHN5Y2hyb290PC14MltuYW1lcyh4MikgJWluJSBwc3ljaHJvb3QkdGlwLmxhYmVsXQpmaXRFUjJfcHN5Y2hyb290ID0gYWNlKHgycHN5Y2hyb290LCBwc3ljaHJvb3QsIG1vZGVsID0gIkVSIiwgdHlwZSA9ICJkaXNjcmV0ZSIsIG1hcmdpbmFsID0gVFJVRSkKCmZpdEVSMl9wc3ljaHJvb3QKCnBsb3RUcmVlKHBzeWNocm9vdCxmc2l6ZT0wLjgsZnR5cGU9ImkiKQpub2RlbGFiZWxzKG5vZGU9MTpwc3ljaHJvb3QkTm5vZGUrTnRpcChwc3ljaHJvb3QpLHBpZT1maXRFUjJfcHN5Y2hyb290JGxpay5hbmMscGllY29sID0geDJjb2wsY2V4PTAuNSkKI3RpcGxhYmVscyhwaWU9dG8ubWF0cml4KHgycHN5Y2hyb290W3BzeWNocm9vdCR0aXAubGFiZWxdLGxldmVscyh4MXBzeWNocm9vdCkpLHBpZWNvbCA9IHgyY29sLGNleD0wLjMpCiNhZGQuc2ltbWFwLmxlZ2VuZChsZWc9c29ydCh1bmlxdWUoeDJwc3ljaHJvb3QpKSxjb2xvcnM9eDJjb2wseD0wLjkqcGFyKCkkdXNyWzFdLAojICAgICAgICAgICAgICAgICAgeT0tbWF4KG5vZGVIZWlnaHRzKHBzeWNocm9vdCkpLGZzaXplPTAuOCkKCiNwbG90VHJlZShNLnRyZWUsZnNpemU9MC44LGZ0eXBlPSJpIikKdGlwbGFiZWxzKHBpZT10by5tYXRyaXgoeDJwc3ljaHJvb3Qsc29ydCh1bmlxdWUoeDJwc3ljaHJvb3QpKSkscGllY29sPXgyY29sLGNleD0wLjMpCmFkZC5zaW1tYXAubGVnZW5kKGNvbG9ycz14MmNvbCxwcm9tcHQ9RkFMU0UseD0wLjkqcGFyKCkkdXNyWzFdLAogICAgICAgICAgICAgICAgICB5PS1tYXgobm9kZUhlaWdodHMocHN5Y2hyb290KSksZnNpemU9MC44KQoKYGBgCgoKI1ByZWRpY3RlZCBjb2xkLWFkYXB0ZWQgcHJvdGVpbiB0cmFpdHMuCiMjI0ZpZ3VyZSAzLjYKYGBge3J9CnBzeWNoX2dlbmVjbHVzdGVyX3N1bW0gPSBhcy5kYXRhLmZyYW1lKHRhYmxlKHBzeWNoX1BDQVQkZ2VuZUNsdXN0ZXIpKQpjb2xuYW1lcyhwc3ljaF9nZW5lY2x1c3Rlcl9zdW1tKSA9IGMoImdlbmVDbHVzdGVyIiwgImZyZXF1ZW5jeSIpCgpoaWdocGNhdGZyZXEgPSBhcy5kYXRhLmZyYW1lKHRhYmxlKHBzeWNoX2hpZ2hQQ0FUJGdlbmVDbHVzdGVyKSkKY29sbmFtZXMoaGlnaHBjYXRmcmVxKSA9IGMoImdlbmVDbHVzdGVyIiwgImZyZXFfaGlnaFBDQVQiKQoKcHN5Y2hfZ2VuZWNsdXN0ZXJfc3VtbSA9IGxlZnRfam9pbihwc3ljaF9nZW5lY2x1c3Rlcl9zdW1tLCBoaWdocGNhdGZyZXEpCnBzeWNoX2dlbmVjbHVzdGVyX3N1bW0kZnJlcV9oaWdoUENBVFtpcy5uYShwc3ljaF9nZW5lY2x1c3Rlcl9zdW1tJGZyZXFfaGlnaFBDQVQpID09IFRSVUVdIDwtIDAKcHN5Y2hfZ2VuZWNsdXN0ZXJfc3VtbSRwZXJjX2hpZ2hQQ0FUID0gcHN5Y2hfZ2VuZWNsdXN0ZXJfc3VtbSRmcmVxX2hpZ2hQQ0FUL3BzeWNoX2dlbmVjbHVzdGVyX3N1bW0kZnJlcXVlbmN5Cgpwc3ljaF9nZW5lY2x1c3Rlcl9zdW1tX25vc2luZ2xldG9ucyA9IHBzeWNoX2dlbmVjbHVzdGVyX3N1bW0gJT4lIGZpbHRlcihmcmVxdWVuY3kgIT0gMSkKCihwZXJIUENBVCA9IGdncGxvdChkYXRhID0gcHN5Y2hfZ2VuZWNsdXN0ZXJfc3VtbSwgYWVzKHggPSBwZXJjX2hpZ2hQQ0FUKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsgdGhlbWVfY2xhc3NpYygpICsgeGxhYigiUGVyY2VudGFnZSBvZiBDRFMgaW4gZ2VuZUNsdXN0ZXIgdGhhdCBhcmUgY2xhc3NpZmllZCBhcyAnaGlnaGx5IGNvbGQgYWRhcHRpdmUnIikpCihwZXJIUENBVF9ub1MgPSBnZ3Bsb3QoZGF0YSA9IHBzeWNoX2dlbmVjbHVzdGVyX3N1bW1fbm9zaW5nbGV0b25zLCBhZXMoeCA9IHBlcmNfaGlnaFBDQVQpKSArIGdlb21faGlzdG9ncmFtKCkgKyB0aGVtZV9jbGFzc2ljKCkgKyB4bGFiKCJQZXJjZW50YWdlIG9mIENEUyBpbiBnZW5lQ2x1c3RlciB0aGF0IGFyZSBjbGFzc2lmaWVkIGFzICdoaWdobHkgY29sZCBhZGFwdGl2ZScsIHNpbmdsZXRvbnMgcmVtb3ZlZCIpKQoKZ2dhcnJhbmdlKHBlckhQQ0FULCBwZXJIUENBVF9ub1MsIGFsaWduID0gJ2gnLCBsYWJlbHMgPSBjKCJBIiwgIkIiKSkKYGBgCgojIyNGaWd1cmUgMy43CmBgYHtyfQpwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0gPSBhcy5kYXRhLmZyYW1lKHRhYmxlKHBzeWNoX1BDQVQkc3RyYWluSUQpKQpjb2xuYW1lcyhwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0pID0gYygic3RyYWluSUQiLCAiZnJlcXVlbmN5IikKaGlnaHBjYXRfYnlzdHJhaW4gPSBhcy5kYXRhLmZyYW1lKHRhYmxlKHBzeWNoX2hpZ2hQQ0FUJHN0cmFpbklEKSkKY29sbmFtZXMoaGlnaHBjYXRfYnlzdHJhaW4pID0gYygic3RyYWluSUQiLCAiZnJlcV9oaWdoUENBVCIpCgpwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0gPSBsZWZ0X2pvaW4ocHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tLCBoaWdocGNhdF9ieXN0cmFpbikKcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJHBlcmNfaGlnaFBDQVQgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kZnJlcV9oaWdoUENBVC9wc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kZnJlcXVlbmN5CgpwZXJjX2hpZ2hQQ0FUID0gcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJHBlcmNfaGlnaFBDQVQKbmFtZXMocGVyY19oaWdoUENBVCkgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kc3RyYWluSUQKc2V0ZGlmZihuYW1lcyhwZXJjX2hpZ2hQQ0FUKSwgUC50cmVlLm5vb3V0JHRpcC5sYWJlbCkKcGh5bG9fUENBVCA9IHBoeWxvc2lnKHRyZWUgPSBQLnRyZWUubm9vdXQsIHggPSBwZXJjX2hpZ2hQQ0FULCB0ZXN0ID0gVFJVRSkKcGh5bG9fUENBVAoKKEhQQ0FUX2J5c3RyYWluID0gZ2dwbG90KGRhdGEgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0sIGFlcyh4ID0gcGVyY19oaWdoUENBVCkpICsgZ2VvbV9oaXN0b2dyYW0oKSArIHRoZW1lX2NsYXNzaWMoKSArIHhsYWIoIlBlcmNlbnRhZ2Ugb2YgaGlnaGx5IGNvbGQgYWRhcHRpdmUgcHJvdGVpbnMgYnkgc3RyYWluIikpCgpwc3ljaF9nZW5vbWVfc3VtbWFyaWVzID0gbGVmdF9qb2luKHBzeWNoX2dlbm9tZV9zdW1tYXJpZXMsIHBzeWNoX3N0cmFpbl9jb2xsZWN0aW9uWyxjKDMsNSwyMSwyNyldKQpwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kc3RyYWluSUQgPSBhcy5jaGFyYWN0ZXIocHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJHN0cmFpbklEKQpwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kc3RyYWluSURbcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJHN0cmFpbklEID09ICJQX3NwX0lBTTEyMDMwXzcyLU8tYyJdIDwtICJQX3NwX0lBTTEyMDMwLTcyLU8tYyIKCnBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSA9IGxlZnRfam9pbihwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0sIHBzeWNoX2dlbm9tZV9zdW1tYXJpZXNbLGMoMTksNSwyMCwyMSldKQpwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kdGVtcHJhbmdlID0gIm1lc29waGlsZSIKcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJHRlbXByYW5nZVtwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kc3RyYWluSUQgPT0gIlBfZnJpZ2lkaWNvbGFfQUNBTTMwNCIgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJHN0cmFpbklEID09ICJQX2ZyaWdpZGljb2xhX0FDQU0zMDkiIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSRzdHJhaW5JRCA9PSAiUF9zcF83Mi1PLWMiIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSRzdHJhaW5JRCA9PSAiUF9zcF9JQU0xMjAzMC03Mi1PLWMiIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSRzdHJhaW5JRCA9PSAiUF91cmF0aXZvcmFuc19BQ0FNMzExIl0gPC0gInBzeWNocm9waGlsZSIKCndpbGNveC50ZXN0KHBlcmNfaGlnaFBDQVQgfiB0ZW1wcmFuZ2UsIGRhdGEgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0pCmtydXNrYWwudGVzdChmcmVxdWVuY3kgfiBJU01FX3NvdXJjZSwgZGF0YSA9IHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSkKa3J1c2thbC50ZXN0KEdlbm9tZS5zaXplLi5icC4gfiBJU01FX3NvdXJjZSwgZGF0YSA9IHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSkKCgooZ2VuZXNfYnlfaXNvc291cmNlID0gZ2dwbG90KGRhdGEgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0sIGFlcyh4ID0gSVNNRV9zb3VyY2UsIHkgPSBmcmVxdWVuY3kpKSArIAogIGdlb21fYm94cGxvdChhbHBoYSA9IDAsIGFlcyhjb2xvciA9IElTTUVfc291cmNlKSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gSVNNRV9zb3VyY2UpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gSVNNRWNvbG9ycykgKwogICAgZ2VvbV9zaWduaWYoY29tcGFyaXNvbnMgPSBsaXN0KGMoIndhcm0gaG9zdCIsICJvdGhlciBob3N0IiksIGMoIndhcm0gaG9zdCIsICJmb29kIiksIGMoIm90aGVyIGhvc3QiLCAibWFyaW5lIiksIGMoIm90aGVyIGhvc3QiLCAidGVycmVzdHJpYWwiKSwgYygiZm9vZCIsICJtYXJpbmUiKSwgYygiZm9vZCIsICJ0ZXJyZXN0cmlhbCIpKSwgbWFwX3NpZ25pZl9sZXZlbCA9IFQpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogICAgeWxhYigiIyBvZiBnZW5lcyBwZXIgZ2Vub21lIikpCgojYWxsIHBhaXJ3aXNlIGNvbXBhcmlzb25zOgojY29tcGFyaXNvbnMgPSBzcGxpdCh0KGNvbWJuKGxldmVscyhwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kSVNNRV9zb3VyY2UpLCAyKSksIHNlcShucm93KHQoY29tYm4obGV2ZWxzKHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSRJU01FX3NvdXJjZSksIDIpKSkpKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJEdlbm9tZS5zaXplLi5icC4sIGcgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kSVNNRV9zb3VyY2UsIHAuYWRqdXN0Lm1ldGhvZCA9ICdCSCcpCnBhaXJ3aXNlLndpbGNveC50ZXN0KHggPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kZnJlcXVlbmN5LCBnID0gcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tJElTTUVfc291cmNlLCBwLmFkanVzdC5tZXRob2QgPSAnQkgnKQoKKEhDQV9ieV90ZW1wcmFuZ2UgPSBnZ3Bsb3QoZGF0YSA9IHBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSwgYWVzKHggPSB0ZW1wcmFuZ2UsIHkgPSBwZXJjX2hpZ2hQQ0FUKSkgKyAKICAgIGdlb21fYm94cGxvdChhbHBoYSA9IDApICsKICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICB5bGFiKCIlIG9mIGdlbmVzIHRoYXQgYXJlIGhpZ2hseSBjb2xkIGFkYXB0ZWQiKSkKCnBzeWNoX1BDQVRfc3RyYWluSURfc3VtbSRJU01FX3NvdXJjZSA9IGZhY3Rvcihwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0kSVNNRV9zb3VyY2UsIGxldmVscyA9IGMoIndhcm0gaG9zdCIsICJvdGhlciBob3N0IiwgImZvb2QiLCAibWFyaW5lIiwgInRlcnJlc3RyaWFsIikpCihIQ0FfYnlfaXNvc291cmNlID0gZ2dwbG90KGRhdGEgPSBwc3ljaF9QQ0FUX3N0cmFpbklEX3N1bW0sIGFlcyh4ID0gSVNNRV9zb3VyY2UsIHkgPSBwZXJjX2hpZ2hQQ0FUKSkgKyAKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLCBhZXMoY29sb3IgPSBJU01FX3NvdXJjZSkpICsgCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IElTTUVfc291cmNlKSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IElTTUVjb2xvcnMpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogICAgeWxhYigiJSBvZiBnZW5lcyB0aGF0IGFyZSBoaWdobHkgY29sZCBhZGFwdGVkIikpCgprcnVza2FsLnRlc3QocGVyY19oaWdoUENBVCB+IElTTUVfc291cmNlLCBkYXRhID0gcHN5Y2hfUENBVF9zdHJhaW5JRF9zdW1tKQoKZ2dhcnJhbmdlKEhDQV9ieV90ZW1wcmFuZ2UsIEhDQV9ieV9pc29zb3VyY2UsIGxhYmVscyA9IGMoIkEiLCAiQiIpLCB3aWR0aHMgPSBjKDEsIDMpKQpgYGAKCiMjI2ZpZ3VyZSAzLjgKYGBge3J9CmhpZ2hQQ0FUbG9jdXMgPSBwc3ljaF9oaWdoUENBVCAlPiUgc2VsZWN0KGxvY3VzX3RhZykgJT4lIHVubGlzdCgpICU+JSB1bm5hbWUoKQpwc3ljaF9QQ0FUJFBDQVQgPSBOQQpwc3ljaF9QQ0FUJFBDQVRbcHN5Y2hfUENBVCRsb2N1c190YWcgJWluJSBoaWdoUENBVGxvY3VzXSA8LSAiaGlnaCIKcHN5Y2hfUENBVCRQQ0FUW2lzLm5hKHBzeWNoX1BDQVQkUENBVCkgPT0gVFJVRV0gPC0gIm5vdCIKcHN5Y2hfUENBVCRQQ0FUID0gZmFjdG9yKHBzeWNoX1BDQVQkUENBVCwgbGV2ZWxzID0gYygibm90IiwgImhpZ2giKSkKCnBzeWNoX1BDQVRfYW5ub3QgPSBsZWZ0X2pvaW4ocHN5Y2hfUENBVCwgbXVsdGlDT0dfZ2VuZXNfY29ycmVjdGVkKQoKKGZ1bmN0aW9uX1BDQVQgPSBnZ3Bsb3QoZGF0YSA9IHBzeWNoX1BDQVRfYW5ub3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gUENBVCwgZmlsbCA9IENPR19jYXRlZ29yeSkpICsgCiAgICBnZW9tX2JhcihzdGF0ID0gJ2NvdW50JywgcG9zaXRpb24gPSAnZmlsbCcpICsgCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBDT0djb2xzKSArCiAgICB0aGVtZV9jbGFzc2ljKCkpCgpDT0dfUENBVF9jaGkgPSBjaGlzcS50ZXN0KHQodGFibGUocHN5Y2hfUENBVF9hbm5vdCRQQ0FULCBwc3ljaF9QQ0FUX2Fubm90JENPR19jYXRlZ29yeSkpKQpDT0dfUENBVF9jaGkKQ09HX1BDQVRfY29yID0gY29ycnBsb3QoQ09HX1BDQVRfY2hpJHJlc2lkdWFscywgaXMuY29yID0gRkFMU0UpCgojYXJyYW5nZSBmdW5jdGlvbl9QQ0FUIHcgY29ycnBsb3QgaW4gaWxsdXN0cmF0b3IKYGBgCgoKCg==